0001: /*
0002: * This file or a portion of this file is licensed under the terms of
0003: * the Globus Toolkit Public License, found in file ../GTPL, or at
0004: * http://www.globus.org/toolkit/download/license.html. This notice must
0005: * appear in redistributions of this file, with or without modification.
0006: *
0007: * Redistributions of this Software, with or without modification, must
0008: * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
0009: * some other similar material which is provided with the Software (if
0010: * any).
0011: *
0012: * Copyright 1999-2004 University of Chicago and The University of
0013: * Southern California. All rights reserved.
0014: */
0015: package org.griphyn.vdl.parser;
0016:
0017: import org.griphyn.vdl.classes.*;
0018: import org.griphyn.vdl.util.*;
0019:
0020: import org.xml.sax.*;
0021: import java.util.List;
0022: import java.util.ArrayList;
0023: import java.util.Map;
0024: import java.util.HashMap;
0025: import java.util.Stack;
0026:
0027: /**
0028: * This class establishes the in-memory construction of Definition
0029: * objects read, and does the callback on the storage interface.
0030: * This class is the content handler for the XML document being parsed.
0031: *
0032: * @author Jens-S. Vöckler
0033: * @author Yong Zhao
0034: * @version $Revision: 50 $
0035: *
0036: * @see Definition
0037: * @see DefinitionHandler
0038: */
0039: public class VDLContentHandler implements ContentHandler {
0040: /**
0041: * This is the callback handler for ready Definitions.
0042: */
0043: private DefinitionHandler m_callback;
0044:
0045: /**
0046: * This is the callback handler for a Definition outside Definitions.
0047: */
0048: private FinalizerHandler m_finalize;
0049:
0050: /**
0051: * Keep the location within the document
0052: */
0053: private Locator m_location;
0054:
0055: /**
0056: * A Hashmap to forward resolve namespaces that were encountered
0057: * during parsing.
0058: */
0059: private Map m_forward;
0060:
0061: /**
0062: * A Hashmap to reverse resolve namespaces that were encountered
0063: * during parsing.
0064: */
0065: private Map m_reverse;
0066:
0067: /**
0068: * The meta elements needs some very special handling (only bypassed).
0069: */
0070: private int m_metamode = 0;
0071:
0072: /**
0073: * Count the depths of elements in the document
0074: */
0075: private int m_depth = 0;
0076:
0077: /**
0078: *
0079: */
0080: private Stack m_stack;
0081:
0082: /**
0083: * ctor.
0084: */
0085: public VDLContentHandler() {
0086: this .m_callback = null;
0087: this .m_finalize = null;
0088: this .m_forward = new HashMap();
0089: this .m_reverse = new HashMap();
0090: }
0091:
0092: /**
0093: * Accessor: This function allows a different DefinitionHandler to
0094: * be set and used.
0095: * @param ds is the new callback object to handle each Definition
0096: * as it becomes ready.
0097: */
0098: public void setDefinitionHandler(DefinitionHandler ds) {
0099: this .m_callback = ds;
0100: }
0101:
0102: /**
0103: * Accessor: This function allows a different FinalizerHandler to
0104: * be set and used. Note, this cannot be used for the Definitions
0105: * elements. In order to reduce the memory footprint, the Definitions
0106: * element will not be maintained!
0107: *
0108: * @param fh is the new callback object to handle a single top-level
0109: * VDL element as it becomes ready.
0110: */
0111: public void setFinalizerHandler(FinalizerHandler fh) {
0112: this .m_finalize = fh;
0113: }
0114:
0115: /**
0116: * Obtains the document locator from the parser. The document location
0117: * can be used to print debug information, i.e the current location
0118: * (line, column) in the document.
0119: *
0120: * @param locator is the externally set current position
0121: */
0122: public void setDocumentLocator(Locator locator) {
0123: this .m_location = locator;
0124: }
0125:
0126: /**
0127: * This method specifies what to do when the parser is at the beginning
0128: * of the document. In this case, we simply print a message for debugging.
0129: */
0130: public void startDocument() throws SAXException {
0131: this .m_depth = 0;
0132: this .m_stack = new Stack();
0133: Logging.instance()
0134: .log("parser", 1, ">>> start of document >>>");
0135: }
0136:
0137: /**
0138: * This method specifies what to do when the parser reached the end
0139: * of the document. In this case, we simply print a message for debugging.
0140: */
0141: public void endDocument() throws SAXException {
0142: Logging.instance().log("parser", 1, "<<< end of document <<<");
0143: }
0144:
0145: /**
0146: * There is a prefix or namespace defined, put the prefix and its URI
0147: * in the HashMap. We can get the URI when the prefix is used here after.
0148: *
0149: * @param prefix the Namespace prefix being declared.
0150: * @param uri the Namespace URI the prefix is mapped to.
0151: */
0152: public void startPrefixMapping(java.lang.String prefix,
0153: java.lang.String uri) throws SAXException {
0154: String p = prefix == null ? null : new String(prefix);
0155: String u = uri == null ? null : new String(uri);
0156: Logging.instance().log("parser", 2,
0157: "adding \"" + p + "\" <=> " + u);
0158:
0159: if (!this .m_forward.containsKey(p))
0160: this .m_forward.put(p, new Stack());
0161: ((Stack) this .m_forward.get(p)).push(u);
0162:
0163: if (!this .m_reverse.containsKey(u))
0164: this .m_reverse.put(u, new Stack());
0165: ((Stack) this .m_reverse.get(u)).push(p);
0166: }
0167:
0168: /**
0169: * Out of the reach of the prefix, remove it from the HashMap.
0170: *
0171: * @param prefix is the prefix that was being mapped previously.
0172: */
0173: public void endPrefixMapping(java.lang.String prefix)
0174: throws SAXException {
0175: String u = (String) ((Stack) this .m_forward.get(prefix)).pop();
0176: String p = (String) ((Stack) this .m_reverse.get(u)).pop();
0177: Logging.instance().log("parser", 2,
0178: "removed \"" + p + "\" <=> " + u);
0179: }
0180:
0181: /**
0182: * Helper function to map prefixes correctly onto the elements.
0183: *
0184: * @param uri is the parser-returned URI that needs translation.
0185: * @return the correct prefix for the URI
0186: */
0187: private String map(String uri) {
0188: if (uri == null || uri.length() == 0)
0189: return "";
0190: Stack stack = (Stack) this .m_reverse.get(uri);
0191: String result = stack == null ? null : (String) stack.peek();
0192: if (result == null || result.length() == 0)
0193: return "";
0194: else
0195: return result + ':';
0196: }
0197:
0198: /**
0199: * This method defines the action to take when the parser begins to parse
0200: * an element.
0201: *
0202: * @param namespaceURI is the URI of the namespace for the element
0203: * @param localName is the element name without namespace
0204: * @param qName is the element name as it appears in the docment
0205: * @param atts has the names and values of all the attributes
0206: */
0207: public void startElement(java.lang.String namespaceURI,
0208: java.lang.String localName, java.lang.String qName,
0209: Attributes atts) throws SAXException {
0210: Logging.instance().log(
0211: "parser",
0212: 3,
0213: "<" + map(namespaceURI) + localName + "> at "
0214: + m_location.getLineNumber() + ":"
0215: + m_location.getColumnNumber());
0216: m_depth++;
0217:
0218: // if in meta mode, skip filling in new elements
0219: if (this .m_metamode == 0) {
0220: java.util.List names = new java.util.ArrayList();
0221: java.util.List values = new java.util.ArrayList();
0222: for (int i = 0; i < atts.getLength(); ++i) {
0223: String name = new String(atts.getLocalName(i));
0224: String value = new String(atts.getValue(i));
0225:
0226: Logging.instance().log(
0227: "parser",
0228: 2,
0229: "attribute " + map(atts.getURI(i)) + name
0230: + "=\"" + value + "\"");
0231: names.add(name);
0232: values.add(value);
0233: }
0234:
0235: VDL object = createObject(qName, names, values);
0236: if (object != null)
0237: m_stack.push(new StackElement(qName, object));
0238: else
0239: throw new SAXException("empty element while parsing");
0240: }
0241:
0242: // check for start of meta mode
0243: if (localName.equals("meta")
0244: && namespaceURI.equals(Definitions.SCHEMA_NAMESPACE)) {
0245: // increase meta level
0246: this .m_metamode++;
0247: }
0248: }
0249:
0250: /**
0251: * The parser is at the end of an element. Each successfully and
0252: * completely parsed Definition will trigger a callback to the
0253: * registered DefinitionHandler.
0254: *
0255: * @param namespaceURI is the URI of the namespace for the element
0256: * @param localName is the element name without namespace
0257: * @param qName is the element name as it appears in the docment
0258: */
0259: public void endElement(java.lang.String namespaceURI,
0260: java.lang.String localName, java.lang.String qName)
0261: throws SAXException {
0262: m_depth--;
0263: Logging.instance().log(
0264: "parser",
0265: 3,
0266: "</" + map(namespaceURI) + localName + "> at "
0267: + m_location.getLineNumber() + ":"
0268: + m_location.getColumnNumber());
0269:
0270: // check for end of meta mode
0271: if (localName.equals("meta")
0272: && namespaceURI.equals(Definitions.SCHEMA_NAMESPACE)) {
0273: // decrease meta level
0274: --this .m_metamode;
0275: }
0276:
0277: // if in meta mode, skip filling in new elements, as they won't
0278: // belong to VDLx (or they might, but should be ignored).
0279: if (this .m_metamode == 0) {
0280: StackElement tos = (StackElement) m_stack.pop();
0281: if (!qName.equals(tos.m_name)) {
0282: Logging.instance().log("default", 0,
0283: "assertion failure");
0284: System.exit(1);
0285: }
0286:
0287: if (!m_stack.empty()) {
0288: // add pieces to lower levels
0289: StackElement peek = (StackElement) m_stack.peek();
0290: if (!setElementRelation(peek.m_name.charAt(0),
0291: peek.m_obj, tos.m_obj))
0292: Logging.instance().log(
0293: "parser",
0294: 0,
0295: "Element " + tos.m_name
0296: + " does not fit into element "
0297: + peek.m_name);
0298: } else {
0299: // run finalizer, if available
0300: if (m_finalize != null)
0301: m_finalize.store(tos.m_obj);
0302: }
0303: }
0304: }
0305:
0306: /**
0307: * This method is the callback function for characters in an element.
0308: * The element is expected to be of mixed content.
0309: *
0310: * @param ch are the characters from the XML document
0311: * @param start is the start position into the array
0312: * @param length is the amount of valid data in the array
0313: */
0314: public void characters(char[] ch, int start, int length)
0315: throws SAXException {
0316: String message = new String(ch, start, length);
0317: if (message.length() > 0) {
0318: if (message.trim().length() == 0)
0319: Logging.instance().log("parser", 3,
0320: "Characters: \' \' x " + message.length());
0321: else
0322: Logging.instance().log("parser", 3,
0323: "Characters: \"" + message + "\"");
0324: if (this .m_metamode == 0) {
0325: // insert text into the only elements possible to carry text
0326: StackElement tos = (StackElement) m_stack.peek();
0327: if (tos.m_obj instanceof Text) {
0328: Text text = (Text) tos.m_obj;
0329: String old = text.getContent();
0330: if (old == null)
0331: text.setContent(message);
0332: else
0333: text.setContent(old + message);
0334: this .log("Text", tos.m_name, message);
0335: } else if (tos.m_obj instanceof Meta) {
0336: Meta meta = (Meta) tos.m_obj;
0337: String content = message.trim();
0338: meta.addContent(content);
0339: this .log("Meta", tos.m_name, content);
0340: }
0341: }
0342: }
0343: }
0344:
0345: /**
0346: * Currently, ignorable whitespace will be ignored.
0347: *
0348: * @param ch are the characters from the XML document
0349: * @param start is the start position into the array
0350: * @param length is the amount of valid data in the array
0351: */
0352: public void ignorableWhitespace(char[] ch, int start, int length)
0353: throws SAXException {
0354: // not implemented
0355: }
0356:
0357: /**
0358: * Receive a processing instruction. Currently, we are just printing
0359: * a debug message that we received a PI.
0360: *
0361: * @param target the processing instruction target
0362: * @param data the processing instruction data, or null if none was supplied.
0363: * The data does not include any whitespace separating it from the target.
0364: */
0365: public void processingInstruction(java.lang.String target,
0366: java.lang.String data) throws SAXException {
0367: Logging.instance().log(
0368: "parser",
0369: 2,
0370: "processing instruction " + target + "=\"" + data
0371: + "\" was skipped!");
0372: }
0373:
0374: /**
0375: * Receive a notification that an entity was skipped. Currently, we
0376: * are just printing a debug message to this fact.
0377: *
0378: * @param name The name of the skipped entity. If it is a parameter
0379: * entity, the name will begin with '%', and if it is the external DTD
0380: * subset, it will be the string "[dtd]".
0381: */
0382: public void skippedEntity(java.lang.String name)
0383: throws SAXException {
0384: Logging.instance().log("parser", 2,
0385: "entity " + name + " was skipped!");
0386: }
0387:
0388: //
0389: // =================================================== our own stuff ===
0390: //
0391:
0392: /**
0393: * Small helper method to bundle repetitive parameters in a template
0394: * for reporting progress.
0395: *
0396: * @param subject is the name of the XML element that is being scrutinized.
0397: * @param name is then name of the element we are working with.
0398: * @param value is the attribute value.
0399: */
0400: private void log(String subject, String name, String value) {
0401: if (value == null)
0402: value = new String();
0403: Logging.instance().log("filler", 3,
0404: subject + "." + name + "=\"" + value + "\"");
0405: }
0406:
0407: /**
0408: * Small helper method to bundle repetitive complaints in a template
0409: * for reporting progress.
0410: *
0411: * @param subject is the name of the XML element that is being scrutinized.
0412: * @param name is then name of the element we are working with.
0413: * @param value is the attribute value.
0414: */
0415: private void complain(String subject, String name, String value) {
0416: if (value == null)
0417: value = new String();
0418: Logging.instance().log(
0419: "default",
0420: 0,
0421: "ignoring " + subject + '@' + name + "=\"" + value
0422: + '"', true);
0423: }
0424:
0425: /**
0426: * This method determines the actively parsed element, creates the
0427: * Java object that corresponds to the element, and sets the member
0428: * variables with the values of the attributes of the element.
0429: *
0430: * @param e is the name of the element
0431: * @param names is a list of attribute names, as strings.
0432: * @param values is a list of attribute values, to match the key list.
0433: * @return A new VDL Java object, which may only be partly constructed.
0434: * @exception IllegalArgumentException if the element name is too short.
0435: */
0436: protected VDL createObject(String e, java.util.List names,
0437: java.util.List values) throws IllegalArgumentException {
0438: if (e == null || e.length() < 1)
0439: throw new IllegalArgumentException("illegal element length");
0440:
0441: // postcondition: string has content w/ length > 0
0442: switch (e.charAt(0)) {
0443: //
0444: // A
0445: //
0446: case 'a':
0447: if (e.equals("argument")) {
0448: Argument argument = new Argument();
0449: for (int i = 0; i < names.size(); ++i) {
0450: String name = (String) names.get(i);
0451: String value = (String) values.get(i);
0452:
0453: if (name.equals("name")) {
0454: this .log(e, name, value);
0455: argument.setName(value);
0456: } else {
0457: this .complain(e, name, value);
0458: }
0459: }
0460: return argument;
0461: }
0462: // unknown
0463: return null;
0464:
0465: //
0466: // C
0467: //
0468: case 'c':
0469: if (e.equals("call")) {
0470: Call call = new Call();
0471: for (int i = 0; i < names.size(); ++i) {
0472: String name = (String) names.get(i);
0473: String value = (String) values.get(i);
0474:
0475: if (name.equals("minIncludeVersion")) {
0476: this .log(e, name, value);
0477: call.setMinIncludeVersion(value);
0478: } else if (name.equals("maxIncludeVersion")) {
0479: this .log(e, name, value);
0480: call.setMaxIncludeVersion(value);
0481: } else if (name.equals("usesspace")) {
0482: this .log(e, name, value);
0483: call.setUsesspace(value);
0484: } else if (name.equals("uses")) {
0485: this .log(e, name, value);
0486: call.setUses(value);
0487: } else {
0488: this .complain(e, name, value);
0489: }
0490: }
0491: return call;
0492: }
0493:
0494: // unknown
0495: return null;
0496:
0497: //
0498: // D
0499: //
0500: case 'd':
0501: if (e.equals("declare")) {
0502: Declare declaration = new Declare("", 0);
0503: for (int i = 0; i < names.size(); ++i) {
0504: String name = (String) names.get(i);
0505: String value = (String) values.get(i);
0506:
0507: if (name.equals("name")) {
0508: this .log(e, name, value);
0509: declaration.setName(value);
0510: } else if (name.equals("container")) {
0511: this .log(e, name, value);
0512: declaration.setContainerType(VDLType
0513: .getContainerType(value));
0514: } else if (name.equals("link")) {
0515: this .log(e, name, value);
0516: declaration.setLink(VDLType.getLinkType(value));
0517: } else {
0518: this .complain(e, name, value);
0519: }
0520: }
0521:
0522: return declaration;
0523:
0524: } else if (e.equals("definitions")) {
0525: Definitions definitions = new Definitions();
0526: for (int i = 0; i < names.size(); ++i) {
0527: String name = (String) names.get(i);
0528: String value = (String) values.get(i);
0529:
0530: if (name.equals("vdlns")) {
0531: this .log(e, name, value);
0532: definitions.setVdlns(value);
0533: } else if (name.equals("version")) {
0534: this .log(e, name, value);
0535: definitions.setVersion(value);
0536: } else if (name.equals("schemaLocation")) {
0537: // ignore
0538: } else {
0539: this .complain(e, name, value);
0540: }
0541: }
0542:
0543: return definitions;
0544:
0545: } else if (e.equals("derivation")) {
0546: Derivation derivation = new Derivation();
0547: for (int i = 0; i < names.size(); ++i) {
0548: String name = (String) names.get(i);
0549: String value = (String) values.get(i);
0550:
0551: if (name.equals("minIncludeVersion")) {
0552: this .log(e, name, value);
0553: derivation.setMinIncludeVersion(value);
0554: } else if (name.equals("maxIncludeVersion")) {
0555: this .log(e, name, value);
0556: derivation.setMaxIncludeVersion(value);
0557: } else if (name.equals("name")) {
0558: this .log(e, name, value);
0559: derivation.setName(value);
0560: } else if (name.equals("namespace")) {
0561: this .log(e, name, value);
0562: derivation.setNamespace(value);
0563: } else if (name.equals("description")) {
0564: this .log(e, name, value);
0565: derivation.setDescription(value);
0566: } else if (name.equals("keyword")) {
0567: this .log(e, name, value);
0568: derivation.setKeyword(value);
0569: } else if (name.equals("title")) {
0570: this .log(e, name, value);
0571: derivation.setTitle(value);
0572: } else if (name.equals("url")) {
0573: this .log(e, name, value);
0574: derivation.setUrl(value);
0575: } else if (name.equals("usesspace")) {
0576: this .log(e, name, value);
0577: derivation.setUsesspace(value);
0578: } else if (name.equals("uses")) {
0579: this .log(e, name, value);
0580: derivation.setUses(value);
0581: } else if (name.equals("version")) {
0582: this .log(e, name, value);
0583: derivation.setVersion(value);
0584: } else {
0585: this .complain(e, name, value);
0586: }
0587: }
0588: return derivation;
0589: }
0590:
0591: // unknown
0592: return null;
0593:
0594: //
0595: // L
0596: //
0597: case 'l':
0598: if (e.equals("lfn")) { // remove const-lfn from here
0599: LFN lfn = new LFN();
0600: for (int i = 0; i < names.size(); ++i) {
0601: String name = (String) names.get(i);
0602: String value = (String) values.get(i);
0603:
0604: if (name.equals("file")) {
0605: this .log(e, name, value);
0606: lfn.setFilename(value);
0607: } else if (name.equals("temporaryHint")) {
0608: this .log(e, name, value);
0609: lfn.setTemporary(value);
0610: } else if (name.equals("dontRegister")) {
0611: this .log(e, name, value);
0612: lfn.setDontRegister(Boolean.valueOf(value)
0613: .booleanValue());
0614: } else if (name.equals("optional")) {
0615: this .log(e, name, value);
0616: lfn.setOptional(new Boolean(value)
0617: .booleanValue());
0618: } else if (name.equals("dontTransfer")) {
0619: if (value.equals("false")) {
0620: this .log(e, name, value);
0621: lfn.setDontTransfer(LFN.XFER_MANDATORY);
0622: } else if (value.equals("true")) {
0623: this .log(e, name, value);
0624: lfn.setDontTransfer(LFN.XFER_NOT);
0625: } else if (value.equals("optional")) {
0626: this .log(e, name, value);
0627: lfn.setDontTransfer(LFN.XFER_OPTIONAL);
0628: } else {
0629: this .complain(e, name, value);
0630: }
0631: } else if (name.equals("isTemporary")) {
0632: // deprecated work-around until phased out.
0633: this .log(e, name, value);
0634: // FIXME: check for null
0635: Logging.instance().log(
0636: "app",
0637: 0,
0638: "using deprecated attribute \"isTemporary\" in LFN "
0639: + lfn.getFilename());
0640: boolean temp = Boolean.valueOf(value)
0641: .booleanValue();
0642: lfn.setDontRegister(temp);
0643: lfn.setDontTransfer(temp ? LFN.XFER_NOT
0644: : LFN.XFER_MANDATORY);
0645: } else if (name.equals("link")) {
0646: this .log(e, name, value);
0647: int link = VDLType.getLinkType(value);
0648: lfn.setLink(link);
0649: } else {
0650: this .complain(e, name, value);
0651: }
0652: } // for
0653: return lfn;
0654:
0655: } else if (e.equals("local")) {
0656: Local temp = new Local("", 0);
0657: for (int i = 0; i < names.size(); ++i) {
0658: String name = (String) names.get(i);
0659: String value = (String) values.get(i);
0660:
0661: if (name.equals("name")) {
0662: this .log(e, name, value);
0663: temp.setName(value);
0664: } else if (name.equals("container")) {
0665: this .log(e, name, value);
0666: temp.setContainerType(VDLType
0667: .getContainerType(value));
0668: } else if (name.equals("link")) {
0669: this .log(e, name, value);
0670: temp.setLink(VDLType.getLinkType(value));
0671: } else {
0672: this .complain(e, name, value);
0673: }
0674: }
0675: return temp;
0676:
0677: } else if (e.equals("list")) {
0678: org.griphyn.vdl.classes.List list = new org.griphyn.vdl.classes.List();
0679: for (int i = 0; i < names.size(); ++i) {
0680: String name = (String) names.get(i);
0681: String value = (String) values.get(i);
0682: this .complain(e, name, value);
0683: }
0684: return list;
0685: }
0686:
0687: // unknown
0688: return null;
0689:
0690: //
0691: // M
0692: //
0693: case 'm':
0694: if (e.equals("meta")) {
0695: Logging.instance().log("app", 2, "entering meta mode");
0696: return new Meta();
0697: }
0698:
0699: // unknown
0700: return null;
0701:
0702: //
0703: // P
0704: //
0705: case 'p':
0706: if (e.equals("profile")) {
0707: Profile prof = new Profile();
0708: for (int i = 0; i < names.size(); ++i) {
0709: String name = (String) names.get(i);
0710: String value = (String) values.get(i);
0711:
0712: if (name.equals("key")) {
0713: this .log(e, name, value);
0714: prof.setKey(value);
0715: } else if (name.equals("namespace")) {
0716: this .log(e, name, value);
0717: prof.setNamespace(value);
0718: } else {
0719: this .complain(e, name, value);
0720: }
0721: }
0722:
0723: return prof;
0724:
0725: } else if (e.equals("pass")) {
0726: Pass pass = new Pass();
0727: for (int i = 0; i < names.size(); ++i) {
0728: String name = (String) names.get(i);
0729: String value = (String) values.get(i);
0730:
0731: if (name.equals("bind")) {
0732: this .log(e, name, value);
0733: pass.setBind(value);
0734: } else {
0735: this .complain(e, name, value);
0736: }
0737: }
0738: return pass;
0739: }
0740:
0741: // unknown
0742: return null;
0743:
0744: //
0745: // S
0746: //
0747: case 's':
0748: if (e.equals("scalar")) {
0749: Scalar scalar = new Scalar();
0750: for (int i = 0; i < names.size(); ++i) {
0751: String name = (String) names.get(i);
0752: String value = (String) values.get(i);
0753: this .complain(e, name, value);
0754: }
0755: return scalar;
0756: }
0757:
0758: // unknown
0759: return null;
0760:
0761: //
0762: // T
0763: //
0764: case 't':
0765: if (e.equals("text")) {
0766: return new Text();
0767: } else if (e.equals("transformation")) {
0768: Transformation trans = new Transformation();
0769: for (int i = 0; i < names.size(); ++i) {
0770: String name = (String) names.get(i);
0771: String value = (String) values.get(i);
0772:
0773: if (name.equals("version")) {
0774: this .log(e, name, value);
0775: trans.setVersion(value);
0776: } else if (name.equals("name")) {
0777: this .log(e, name, value);
0778: trans.setName(value);
0779: } else if (name.equals("namespace")) {
0780: this .log(e, name, value);
0781: trans.setNamespace(value);
0782: } else if (name.equals("description")) {
0783: this .log(e, name, value);
0784: trans.setDescription(value);
0785: } else if (name.equals("keyword")) {
0786: this .log(e, name, value);
0787: trans.setKeyword(value);
0788: } else if (name.equals("title")) {
0789: this .log(e, name, value);
0790: trans.setTitle(value);
0791: } else if (name.equals("url")) {
0792: this .log(e, name, value);
0793: trans.setUrl(value);
0794: } else if (name.equals("version")) {
0795: this .log(e, name, value);
0796: trans.setVersion(value);
0797: } else if (name.equals("argumentSeparator")) {
0798: this .log(e, name, value);
0799: trans.setArgumentSeparator(value);
0800: } else {
0801: this .complain(e, name, value);
0802: }
0803: }
0804: return trans;
0805: }
0806:
0807: // unknown
0808: return null;
0809:
0810: //
0811: // U
0812: //
0813: case 'u':
0814: if (e.equals("use")) {
0815: Use use = new Use();
0816: for (int i = 0; i < names.size(); ++i) {
0817: String name = (String) names.get(i);
0818: String value = (String) values.get(i);
0819:
0820: if (name.equals("name")) {
0821: this .log(e, name, value);
0822: use.setName(value);
0823: } else if (name.equals("prefix")) {
0824: this .log(e, name, value);
0825: use.setPrefix(value);
0826: } else if (name.equals("separator")) {
0827: this .log(e, name, value);
0828: use.setSeparator(value);
0829: } else if (name.equals("suffix")) {
0830: this .log(e, name, value);
0831: use.setSuffix(value);
0832: } else if (name.equals("link")) {
0833: this .log(e, name, value);
0834: use.setLink(VDLType.getLinkType(value));
0835: } else {
0836: this .complain(e, name, value);
0837: }
0838: }
0839: return use;
0840: }
0841:
0842: // unknown
0843: return null;
0844:
0845: default:
0846: // FIXME: shouldn't this be an exception?
0847: Logging.instance().log("filler", 0,
0848: "Error: No rules defined for element " + e);
0849: return null;
0850: }
0851: }
0852:
0853: /**
0854: * This method sets the relations between the currently finished XML
0855: * element and its containing element in terms of Java objects.
0856: * Usually it involves adding the object to the parent's child object
0857: * list.
0858: *
0859: * @param initial is the first charactor of the parent element name
0860: * @param parent is a reference to the parent's Java object
0861: * @param child is the completed child object to connect to the parent
0862: * @return true if the element was added successfully, false, if the
0863: * child does not match into the parent.
0864: */
0865: protected boolean setElementRelation(char initial, VDL parent,
0866: VDL child) {
0867: switch (initial) {
0868: //
0869: // A
0870: //
0871: case 'a':
0872: if (parent instanceof Argument && child instanceof Leaf) {
0873: // addLeaf is self-checking
0874: ((Argument) parent).addLeaf((Leaf) child);
0875: return true;
0876: }
0877: return false;
0878:
0879: //
0880: // C
0881: //
0882: case 'c':
0883: if (parent instanceof Call) {
0884: Call c = (Call) parent;
0885: if (child instanceof Pass) {
0886: ((Call) parent).addPass((Pass) child);
0887: return true;
0888: } else if (child instanceof Meta) {
0889: // dunno
0890: return true;
0891: }
0892: }
0893: return false;
0894:
0895: //
0896: // D
0897: //
0898: case 'd':
0899: if (parent instanceof Declare && child instanceof Value) {
0900: // setValue is self-checking
0901: ((Declare) parent).setValue((Value) child);
0902: return true;
0903:
0904: } else if (parent instanceof Definitions
0905: && child instanceof Definition) {
0906: // again, self-checking
0907: ((Definitions) parent)
0908: .addDefinition((Definition) child);
0909:
0910: // This means we have finished parsing a TR or DV. Invoke callback!
0911: if (m_callback != null) {
0912: // Logging.instance().log( "app", 3, "invoking callback for " + ((Definition) child).shortID() );
0913: m_callback.store((Definition) child);
0914: }
0915:
0916: // FIXME: decrease memory footprint!
0917: ((Definitions) parent).removeAllDefinition();
0918: return true;
0919:
0920: } else if (parent instanceof Derivation) {
0921: Derivation d = (Derivation) parent;
0922: if (child instanceof Pass) {
0923: d.addPass((Pass) child);
0924: return true;
0925: } else if (child instanceof Meta) {
0926: // dunno
0927: return true;
0928: }
0929: }
0930:
0931: // unknown
0932: return false;
0933:
0934: //
0935: // L
0936: //
0937: case 'l':
0938: if (parent instanceof org.griphyn.vdl.classes.List
0939: && child instanceof Scalar) {
0940: ((org.griphyn.vdl.classes.List) parent)
0941: .addScalar((Scalar) child);
0942: return true;
0943: } else if (parent instanceof Local
0944: && child instanceof Value) {
0945: // setValue is self-checking
0946: ((Local) parent).setValue((Value) child);
0947: return true;
0948: }
0949:
0950: // LFN is a *leaf* !!
0951:
0952: // unknown
0953: return false;
0954:
0955: //
0956: // M
0957: //
0958: case 'm':
0959: if (parent instanceof Meta) {
0960: // dunno whatta do
0961: return true;
0962: }
0963:
0964: // unknown
0965: return false;
0966:
0967: //
0968: // P
0969: //
0970: case 'p':
0971: if (parent instanceof Profile && child instanceof Leaf) {
0972: ((Profile) parent).addLeaf((Leaf) child);
0973: return true;
0974:
0975: } else if (parent instanceof Pass && child instanceof Value) {
0976: ((Pass) parent).setValue((Value) child);
0977: return true;
0978: }
0979:
0980: // unknown
0981: return false;
0982:
0983: //
0984: // S
0985: //
0986: case 's':
0987: if (parent instanceof Scalar && child instanceof Leaf) {
0988: ((Scalar) parent).addLeaf((Leaf) child);
0989: return true;
0990: }
0991:
0992: // unknown
0993: return false;
0994:
0995: //
0996: // T
0997: //
0998: case 't':
0999: if (parent instanceof Transformation) {
1000: Transformation trans = (Transformation) parent;
1001: if (child instanceof Declare) {
1002: trans.addDeclare((Declare) child);
1003: return true;
1004: } else if (child instanceof Argument) {
1005: trans.addArgument((Argument) child);
1006: return true;
1007: } else if (child instanceof Call) {
1008: trans.addCall((Call) child);
1009: return true;
1010: } else if (child instanceof Local) {
1011: trans.addLocal((Local) child);
1012: return true;
1013: } else if (child instanceof Profile) {
1014: trans.addProfile((Profile) child);
1015: return true;
1016: } else if (child instanceof Meta) {
1017: // dunno
1018: return true;
1019: }
1020: }
1021: // Text is a *leaf* !!
1022: return false;
1023:
1024: //
1025: // U
1026: //
1027: case 'u':
1028: // Use is a *leaf* !!
1029: return false;
1030:
1031: default:
1032: // FIXME: shouldn't this be an exception?
1033: Logging.instance().log("filler", 0,
1034: "Error: unable to join child to parent");
1035: return false;
1036: }
1037: }
1038: }
|