@NbBundle.Messages({ "# {0} - NS prefix", "ERR_undeclaredElementPrefix=XML namespace prefix ''{0}'' is undeclared" }) @Override public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { this.tagName = localName; FxNode newElement; start = contentLocator.getElementOffset(); end = contentLocator.getEndOffset(); addElementErrors(); if (uri == null && !qName.equals(localName)) { // undeclared prefix int prefColon = qName.indexOf(':'); String prefix = qName.substring(0, prefColon); addError("undeclared-prefix", ERR_undeclaredElementPrefix(prefix)); newElement = accessor.createErrorElement(localName); } else if ("".equals(localName)) { newElement = accessor.createErrorElement(localName); } else if (FXML_FX_NAMESPACE.equals(uri)) { newElement = handleFxmlElement(localName, atts); } else { // non-fx namespace, should be either an instance, or a property or an event String eventName = FxXmlSymbols.getEventHandlerName(localName); if (rootComponent == null || FxXmlSymbols.isClassTagName(localName)) { newElement = handleClassTag(localName, atts); } else if (eventName != null) { newElement = handleEventHandlerTag(eventName); } else { newElement = handlePropertyTag(localName, atts); } } if (newElement == null) { throw new IllegalStateException(); } initElement(newElement); FxNode newNode = newElement; // if not broken attempt to attach the Element to a parent if (!newElement.isBroken()) { if (newElement instanceof FxObjectBase) { newNode = attachInstance((FxObjectBase) newElement); } else if (newElement instanceof PropertyValue) { newNode = attachProperty((PropertyValue) newElement); } } attachChildNode(newNode); // process attributes, iff it is an instance. Attribute processing needs the node pushed // on the stack, so it is delayed after attachChildNode if (newNode.getKind() == Kind.Instance) { processInstanceAttributes(atts); } }
/** * Processes ?include directive * * @param include */ @NbBundle.Messages({ "ERR_missingIncludeName=Missing include name", "# {0} - attribute name", "ERR_unexpectedIncludeAttribute=Unexpected attribute in fx:include: {0}" }) private FxNode handleFxInclude(Attributes atts, String localName) { String include = null; for (int i = 0; i < atts.getLength(); i++) { String attName = atts.getLocalName(i); if (FX_ATTR_REFERENCE_SOURCE.equals(attName)) { include = atts.getValue(i); } else { String qName = atts.getQName(i); addAttributeError( qName, "unexpected-include-attribute", ERR_unexpectedIncludeAttribute(qName), qName); } } if (include == null) { // must be some text, otherwise = error addAttributeError( ContentLocator.ATTRIBUTE_TARGET, "missing-included-name", ERR_missingIncludeName()); FxNode n = accessor.createErrorElement(localName); initElement(n); addError("invalid-fx-element", ERR_invalidFxElement(localName), localName); return n; } // guide: fnames starting with slash are treated relative to the classpath FxInclude fxInclude = accessor.createInclude(include); return fxInclude; }
@NbBundle.Messages({ "ERR_missingLanguageName=Language name is missing", "ERR_duplicateLanguageDeclaration=Language is already declared" }) private FxNode handleFxLanguage(String language) { LanguageDecl decl = accessor.createLanguage(language); if (language == null) { addAttributeError( ContentLocator.ATTRIBUTE_TARGET, "missing-language-name", ERR_missingLanguageName()); accessor.makeBroken(decl); } else { if (this.language != null) { // error, language can be specified only once: addError( new ErrorMark( start, end - start, "duplicate-language", ERR_duplicateLanguageDeclaration(), fxModel.getLanguage())); accessor.makeBroken(decl); } else if (isTopLevel()) { this.language = decl; } } return decl; }
@NbBundle.Messages({ "# {0} - tag name", "ERR_invalidFxElement=Unknown element in fx: namespace: {0}", "ERR_duplicateDefinitions=Duplicate 'definitions' element" }) private FxNode handleFxmlElement(String localName, Attributes atts) { if (FX_DEFINITIONS.equals(localName)) { definitions++; if (definitionsFound) { // error, defs cannot be nested or used more than once. Ignore. addError("duplicate-definitions", ERR_duplicateDefinitions()); } FxNode n = accessor.createElement(localName); definitionsNode = accessor.i(n); return n; } else if (FX_COPY.equals(localName)) { return handleFxReference(atts, true); } else if (FX_REFERENCE.equals(localName)) { return handleFxReference(atts, false); } else if (FX_INCLUDE.equals(localName)) { return handleFxInclude(atts, localName); } else { // error, invalid fx: element FxNode n = accessor.createErrorElement(localName); initElement(n); addError("invalid-fx-element", ERR_invalidFxElement(localName), localName); return n; } }
/** * Builds the argument invocation string for calling a constructor * * @param classVariables The collection of member variables as XMLElements * @param constructorArguments The set of names for constructor arguments * @param allocatedMemberVariables The set of member variables already allocated * @param element The specific 'new' xml element */ private static String buildArguments( Vector classVariables, Set constructorArguments, Set allocatedMemberVariables, IXMLElement element) throws IOException { XMLUtil.checkExpectedNode("new", element); boolean comma = false; String arguments = ""; for (Enumeration e = element.enumerateChildren(); e.hasMoreElements(); ) { IXMLElement argument = (IXMLElement) e.nextElement(); String argType = ModelAccessor.getValueType(argument); String value = ModelAccessor.getValue(argument); /* Exclude cases where we do nothing to the value */ if (!primitives.contains(argType) && !value.equals("true") && !value.equals("false")) { // CASE 0: Translate 'this' if (value.equalsIgnoreCase("this")) { value = "m_id"; } // CASE 1: It is a singleton member variable which must be mapped to the singleton else if (allocatedMemberVariables.contains(value)) { String singletonType = getVariableType(classVariables, value); if (primitives.contains(singletonType)) { value = "(" + singletonType + ") singleton(" + value + ")"; } else value = "singleton(" + value + ")"; } // CASE 2: It is a constructor argument else if (constructorArguments.contains(value)) { // Do nothing, just use the string as is. } // CASE 3: Test for error - using a member before initializing it else if (!allocatedMemberVariables.contains(value) && isMember(classVariables, value)) { value = "!ERROR: Cannot use " + value + " without prior initialization."; } // Otherwise it is a string or enumerataion else if (argType.equals("string") || // It is an enumeartion of some kind ModelAccessor.isEnumeration(argType) || argType.equals("symbol")) { value = "LabelStr(\"" + XMLUtil.escapeQuotes(value) + "\")"; } // If we fall through to here, there is an error. else value = "!ERROR:BAD ASSIGNMENT"; } // CASE 3: It is a true or false value if (comma) arguments = arguments + ", "; arguments = arguments + value; comma = true; } return arguments; }
/** * Helper method to generate the signatures for binding the factory. Must account for the * inheritance relationships for any arguments that are classes. Ths, each argument can * potentially result in a range of values for type, and we have to handle the cross product of * all of these. */ private static Vector makeFactoryNames(IXMLElement constructor) { String factoryName = XMLUtil.nameOf(constructor.getParent()); Vector allPermutations = new Vector(); for (Enumeration e = constructor.enumerateChildren(); e.hasMoreElements(); ) { IXMLElement element = (IXMLElement) e.nextElement(); if (!element.getName().equals("arg")) { break; } String argType = XMLUtil.typeOf(element); Vector argTypeAlternates = new Vector(); argTypeAlternates.add(argType); if (ModelAccessor.isClass(argType)) { List ancestors = ModelAccessor.getAncestors(argType); if (ancestors != null) argTypeAlternates.addAll(ancestors); } allPermutations.add(argTypeAlternates); } // Generate all the signatures Vector factoryNames = new Vector(); makeFactoryNames(factoryName, allPermutations, 0, factoryNames); return factoryNames; }
private FxNode handleEventHandlerTag(String eventName) { FxNode node = accessor.createEventHandler(eventName); FxNode parent = nodeStack.peek(); if (!(parent instanceof FxInstance)) { accessor.makeBroken(node); } return node; }
public static void writeTypedefs(IndentWriter writer, IXMLElement klass) throws IOException { String name = ModelAccessor.getClassName(klass); if (!ModelAccessor.isPredefinedClass(name)) { SharedWriter.writeTypedefs(writer, name); writer.write("typedef ObjectDomain " + name + "Domain;\n\n"); } }
@NbBundle.Messages({"# {0} - tag name", "ERR_invalidPropertyName=Invalid property name: {0}"}) private FxNode handlePropertyTag(String propName, Attributes atts) { PropertyValue pv; int errorAttrs = 0; for (int i = 0; i < atts.getLength(); i++) { String uri = atts.getURI(i); if (uri != null) { String qn = atts.getQName(i); errorAttrs++; addAttributeError( qn, "property-namespaced-attribute", ERR_propertyElementNamespacedAttribute(qn), qn); } } int stProp = FxXmlSymbols.findStaticProperty(propName); switch (stProp) { case -1: // simple property if (!Utilities.isJavaIdentifier(propName)) { addError( new ErrorMark( start, end, "invalid-property-name", ERR_invalidPropertyName(propName), propName)); } if (errorAttrs == atts.getLength()) { pv = handleSimpleProperty(propName, atts); } else { pv = handleMapProperty(propName, atts); } break; case -2: // broken name, but must create a node pv = accessor.makeBroken(accessor.createProperty(propName, false)); // do not add the property to the parent, it's broken beyond repair addError( new ErrorMark( start, end, "invalid-property-name", ERR_invalidPropertyName(propName), propName)); break; default: // static property, just ignore for now pv = handleStaticProperty( propName.substring(0, stProp), propName.substring(stProp + 1), atts); break; } return pv; }
private void attachChildNode(FxNode node) { FxNode top = nodeStack.peek(); i(top).addChild(node); // if (!node.isBroken() && (node.getKind() != FxNode.Kind.Element)) { accessor.attach(node, fxModel); if (!node.isBroken()) { accessor.addChild(top, node); } if (i(node).isElement()) { pushInstance(node); } }
private FxNode processEventHandlerAttribute(String event, String content) { EventHandler eh; if (content != null && content.startsWith(EVENT_HANDLER_METHOD_PREFIX)) { eh = accessor.asMethodRef(accessor.createEventHandler(event)); accessor.addContent(eh, content.substring(1)); } else { eh = accessor.createEventHandler(event); if (content != null && content.length() > 0) { accessor.addContent(eh, content); } } return eh; }
private FxNode handleEventContent(CharSequence content) { EventHandler eh = (EventHandler) nodeStack.peek(); if (eh.isScript() && !eh.hasContent()) { if (content.length() == 0) { throw new UnsupportedOperationException(); } else { if (content.charAt(0) == '#') { content = content.subSequence(1, content.length()); eh = accessor.asMethodRef(eh); } } } accessor.addContent(eh, content); return eh; }
@NbBundle.Messages({ "ERR_instructionBadPlacement=Bad placement for processing instruction. Must be before all elements." }) @Override public void processingInstruction(String target, String data) throws SAXException { start = contentLocator.getElementOffset(); end = contentLocator.getEndOffset(); addElementErrors(); FxNode node = null; boolean broken = false; if (!isTopLevel() || rootComponent != null) { addError("instruction-bad-placement", ERR_instructionBadPlacement()); broken = true; } if (FX_IMPORT.equals(target)) { node = handleFxImport(data); } else if (FX_LANGUAGE.equals(target)) { node = handleFxLanguage(data); } else if (!"xml".equals(target)) { handleErrorInstruction(target, data); } if (node == null) { return; } i(node).makePI().startAt(start).endsAt(end); if (broken) { accessor.makeBroken(node); } attachChildNode(node); }
@Override public void startDocument() throws SAXException { fxModel = accessor.newModel(sourceURL, imports, instanceDefinitions); initElement(fxModel); nodeStack.push(fxModel); }
/** @brief Generates the signature for the class constructors */ private static void generateSignature(IndentWriter writer, IXMLElement constructor) throws IOException { assert (DebugMsg.debugMsg("ClassWriter", "Begin ClassWriter::generateSignature")); writer.write("constructor("); boolean comma = false; for (Enumeration e = constructor.enumerateChildren(); e.hasMoreElements(); ) { IXMLElement element = (IXMLElement) e.nextElement(); if (!element.getName().equals("arg")) { break; } String argType = XMLUtil.typeOf(element); String argName = XMLUtil.getAttribute(element, "name"); if (comma) { writer.write(", "); } // Argument are structured as: <arg name="argName" type="argType"/> if (argType.equals(NddlXmlStrings.x_int)) writer.write("int " + argName); else if (argType.equals(NddlXmlStrings.x_float)) writer.write("double " + argName); else if (argType.equals(NddlXmlStrings.x_boolean)) writer.write("bool " + argName); else if (argType.equals(NddlXmlStrings.x_string) || argType.equals(NddlXmlStrings.x_symbol) || ModelAccessor.isEnumeration(argType)) writer.write("const LabelStr& " + argName); else writer.write("const " + argType + "Id& " + argName); comma = true; } writer.write(")"); assert (DebugMsg.debugMsg("ClassWriter", "End ClassWriter::generateSignature")); }
@NbBundle.Messages({ "# {0} - attribute local name", "ERR_unexpectedReferenceAttribute=Unexpected attribute in fx:reference or fx:copy: {0}", "ERR_missingReferenceSource=Missing 'source' attribute in fx:reference or fx:copy" }) private FxNode handleFxReference(Attributes atts, boolean copy) { String refId = null; String id = null; for (int i = 0; i < atts.getLength(); i++) { String ns = atts.getURI(i); String name = atts.getLocalName(i); if (!FXML_FX_NAMESPACE.equals(ns)) { if (FX_ATTR_REFERENCE_SOURCE.equals(name) && refId == null) { refId = atts.getValue(i); } else if (!copy) { // error, references do not support normal attributes addAttributeError( atts.getQName(i), "invalid-reference-attribute", ERR_unexpectedReferenceAttribute(name), name); } } else { if (FX_ID.equals(name) && id == null) { id = atts.getValue(i); } else { // error, unexpected attribute addAttributeError( atts.getQName(i), "invalid-reference-attribute", ERR_unexpectedReferenceAttribute(name), name); } } } FxObjectBase ref = accessor.createCopyReference(copy, refId); if (refId == null || "".equals(refId)) { // error, no source attribute found addError("missing-reference-source", ERR_missingReferenceSource()); accessor.makeBroken(ref); } return ref; }
@Override public void endDocument() throws SAXException { addElementErrors(); accessor.initModel(fxModel, controllerName, rootComponent, language); int end = contentLocator.getElementOffset(); i(fxModel).endContent(end).endsAt(end, true); // attempt to fix up unclosed elements // fixNodes(i(fxModel), end); }
private PropertyValue handleMapProperty(String propName, Attributes atts) { Map<String, CharSequence> contents = new HashMap<String, CharSequence>(); for (int i = 0; i < atts.getLength(); i++) { String uri = atts.getURI(i); if (uri != null) { continue; } contents.put(atts.getLocalName(i), atts.getValue(i)); } return accessor.createMapProperty(propName, contents); }
/** * Processes instance (non-static) property. As per examples in Guides, instance property element * must NOT have any attributes; otherwise it corresponds to an readonly Map element, and the * property must be of the Map type. * * @param propName * @param atts As */ @NbBundle.Messages({ "# {0} - attribute name", "ERR_propertyElementNamespacedAttribute=Property elements may not contain attributes with namespace: {0}" }) private PropertyValue handleSimpleProperty(String propName, Attributes atts) { PropertyValue p; // no relevant attributes to use, real simple property then p = accessor.createProperty(propName, false); return p; }
private static String getVariableType(Vector classVariables, String name) { String type = "!ERROR"; for (int i = 0; i < classVariables.size(); i++) { IXMLElement variable = (IXMLElement) classVariables.elementAt(i); if (XMLUtil.nameOf(variable).equals(name)) { type = XMLUtil.getAttribute(variable, "type"); String _class = XMLUtil.getAttribute(variable.getParent(), "name"); if (ModelAccessor.isEnumeration(_class + "::" + type)) type = _class + "::" + type; break; } } return type; }
public static void generateImplementation(IndentWriter writer, IXMLElement klass) throws IOException { String superClass = ModelAccessor.getSuperClass(klass); String name = XMLUtil.getAttribute(klass, "name"); if (ModelAccessor.isPredefinedClass(name)) { writer.write("// SKIPPING IMPLEMENTATION FOR BUILT-IN CLASS " + name + "\n\n"); return; } ModelAccessor.setCurrentObjectType(name); String longname = XMLUtil.qualifiedName(klass); boolean extendsBuiltIn = ModelAccessor.isPredefinedClass(superClass); String superCppClass = ModelAccessor.getCppClass(superClass); writer.write("\n"); SharedWriter.generateFileLocation(writer, klass); writer.write( longname + "::" + name + "(const PlanDatabaseId& planDatabase, const LabelStr& name)\n"); if (extendsBuiltIn) writer.write(" : " + superCppClass + "(planDatabase, \"" + name + "\", name, true)"); else writer.write(" : " + superCppClass + "(planDatabase, \"" + name + "\", name)"); writer.write(" {\n"); writer.write("}\n"); writer.write( longname + "::" + name + "(const PlanDatabaseId& planDatabase, const LabelStr& type, const LabelStr& name)\n"); if (extendsBuiltIn) writer.write(" : " + superCppClass + "(planDatabase, type, name, true)"); else writer.write(" : " + superCppClass + "(planDatabase, type, name)"); writer.write(" {\n"); writer.write("}\n"); writer.write(longname + "::" + name + "(const ObjectId& parent, const LabelStr& name)\n"); if (extendsBuiltIn) writer.write(" : " + superCppClass + "(parent, \"" + name + "\", name, true)"); else writer.write(" : " + superCppClass + "(parent, \"" + name + "\", name)"); writer.write(" {}\n"); writer.write( longname + "::" + name + "(const ObjectId& parent, const LabelStr& type, const LabelStr& name)\n"); if (extendsBuiltIn) writer.write(" : " + superCppClass + "(parent, type, name, true)"); else writer.write(" : " + superCppClass + "(parent, type, name)"); writer.write(" {}\n"); Vector classVariables = klass.getChildrenNamed("var"); SharedWriter.defineHandleDefaults(writer, klass, classVariables); generateChildren(writer, klass); ModelAccessor.resetCurrentObjectType(); }
private FxNode handleInstanceContent(CharSequence seq) { // find among properties as setter, which is marked as implicit. If there's none, create one. PropertySetter defaultSetter = null; for (PropertyValue p : current.getProperties()) { if (p instanceof PropertySetter) { PropertySetter ps = (PropertySetter) p; if (ps.isImplicit()) { defaultSetter = ps; } } } if (defaultSetter == null) { defaultSetter = accessor.createProperty(null, true); i(defaultSetter).startAt(contentLocator.getElementOffset()); attachProperty(defaultSetter); attachChildNode(defaultSetter); } accessor.addContent(defaultSetter, seq); return defaultSetter; }
/** * Processes "import" PI. Checks syntax of the identifier * * @param data */ @NbBundle.Messages({ "ERR_importNotJavaIdentifier=Imported symbol must be a class or package name.", "ERR_importInsideElement=Imports must be at top level, not nested in elements", "ERR_importFollowsRoot=Import must not follow the root element", "ERR_missingImportIdentifier=Identifier missing in ?import instruction" }) private FxNode handleFxImport(String data) { if (data.endsWith("?")) { // recovery from unterminated ?> -- the lexer will report ? as part of PI data. data = data.substring(0, data.length() - 1); } if ("".equals(data)) { addError("missing-import-identifier", ERR_missingImportIdentifier()); return null; } int lastDot = data.lastIndexOf('.'); boolean starImport = false; if (lastDot != -1 && lastDot < data.length() - 1) { if (FX_IMPORT_STAR.equals(data.substring(lastDot + 1))) { starImport = true; data = data.substring(0, lastDot); } } ImportDecl decl = accessor.createImport(data, starImport); if (!FxXmlSymbols.isQualifiedIdentifier(data)) { addAttributeError( ContentLocator.ATTRIBUTE_DATA, "import-not-java-identifier", ERR_importNotJavaIdentifier(), data); accessor.makeBroken(decl); } imports.add(decl); return decl; }
@NbBundle.Messages({ "ERR_mixedContentNotAllowed=Mixed content is not allowed in property elements" }) private FxNode handlePropertyContent(CharSequence seq) { FxNode node = nodeStack.peek(); if (!(node instanceof PropertySetter)) { addError("unexpected-characters", ERR_unexpectedCharacters()); return null; } // if the property has already received some bean instances, report // invalid content PropertySetter ps = (PropertySetter) node; if (ps.getValues() != null) { addError("mixed-content-not-allowed", ERR_mixedContentNotAllowed()); } accessor.addContent((PropertySetter) node, seq); return node; }
@NbBundle.Messages({ "# {0} - parent tag local name", "ERR_doesNotAcceptProperty=The parent element {0} does not accept properties" }) private FxNode attachProperty(PropertyValue p) { // FIXME - if 'current' is null, if (current == null) { FxNode node = nodeStack.peek(); addError( new ErrorMark( start, end - start, "parent-not-accept-property", ERR_doesNotAcceptProperty(node.getSourceName()), node)); accessor.makeBroken(p); } return p; }
/** * The pattern we have is to generate the schema through an implementation of thie schema() * function which will be invoked by the client. */ public static void generate(IndentWriter writer) throws IOException { writer.write("namespace NDDL {\n"); writer.indent(); // Implement expected initialization hooks writer.write("// Boot-strap code to initialize schema\n"); writer.write( "extern \"C\" SchemaId loadSchema(const SchemaId& schema,const RuleSchemaId& ruleSchema)\n{\n"); writer.indent(); String modelName = ModelAccessor.getModelName(); if (modelName == null) throw new RuntimeException("Failed to set model name. Bug in NddlCompiler"); writer.write("SchemaId id = schema;\n"); // Register Constraints writer.write("// Register Constraints\n"); for (Iterator it = s_constraintRegistrations.iterator(); it.hasNext(); ) { String constraint = (String) it.next(); writer.write(constraint + ";\n"); } writer.write("// Invoke commands to populate schema with type definitions\n"); // Iterate over all type definition commands for (int i = 0; i < s_objectTypeCommands.size(); i++) { writer.write("id->" + s_objectTypeCommands.elementAt(i) + ";\n"); } // Iterate over all type definition commands for (int i = 0; i < s_commands.size(); i++) { writer.write("id->" + s_commands.elementAt(i) + ";\n"); } // Force allocation of type factories. This should do a mapping for external names // to internal writer.write("// Force allocation of model specific type factories\n"); // Allocate Factories writer.write("// Allocate factories\n"); for (Iterator it = s_factoryAllocations.iterator(); it.hasNext(); ) { String command = (String) it.next(); writer.write(command); } // Iterate over all rules and allocate singletons - this registers rules writer.write("// Allocate rules\n"); Set ruleNames = RuleWriter.getRules(); for (Iterator it = ruleNames.iterator(); it.hasNext(); ) { String ruleName = (String) it.next(); writer.write("ruleSchema->registerRule((new " + ruleName + "())->getId());\n"); } writer.write("return id;\n"); writer.unindent(); writer.write("}\n\n"); writer.unindent(); writer.write("}\n"); }
private static String makeArgumentType(String argType) { if (primitives.contains(argType)) return argType; else if (argType.equals("string") || ModelAccessor.isEnumeration(argType)) return "LabelStr"; else return argType + "Id"; }
public static void declareDefaultConstructor(IndentWriter writer, String superClass) throws IOException { // If it is a built in class then define the default 'constructor' call if (ModelAccessor.isPredefinedClass(superClass)) writer.write("virtual void constructor(); // default constructoror\n"); }
private PropertyValue handleStaticProperty(String className, String propName, Attributes atts) { // FIXME - check that attributes are empty StaticProperty s = accessor.createStaticProperty(propName, className); return s; }
public static void defineConstructor(IndentWriter writer, IXMLElement constructor) throws IOException { assert (DebugMsg.debugMsg("ClassWriter", "Begin ClassWriter::defineConstructor")); IXMLElement klass = constructor.getParent(); SharedWriter.generateFileLocation(writer, klass); if (klass == null) { throw new RuntimeException("missing class for constructor"); } String longname = XMLUtil.nameOf(klass); writer.write("void " + longname + "::"); generateSignature(writer, constructor); writer.write(" {\n"); writer.indent(); // If the constructor has a call to the super class, invoke it. assert (DebugMsg.debugMsg( "ClassWriter", "ClassWriter::defineConstructor - getting children named 'super'")); Vector superCalls = constructor.getChildrenNamed("super"); assert (DebugMsg.debugMsg( "ClassWriter", "ClassWriter::defineConstructor - " + superCalls.size() + " children named retrieved")); if (!superCalls.isEmpty()) { assert (DebugMsg.debugMsg("ClassWriter", "ClassWriter::defineConstructor - calling super")); if (superCalls.size() > 1) writer.write("!ERROR: AT MOST ONE CALL TO SUPER ALLOWED\n"); IXMLElement superCall = (IXMLElement) superCalls.elementAt(0); String superClass = ModelAccessor.getParentClassName(klass); String superCppClass = ModelAccessor.getCppClass(superClass); writer.write(superCppClass + "::constructor("); String comma = ""; Enumeration arguments = superCall.enumerateChildren(); while (arguments.hasMoreElements()) { IXMLElement argument = (IXMLElement) arguments.nextElement(); String value = ModelAccessor.getValue(argument); if (argument.getName().equals("value") && XMLUtil.getAttribute(argument, "type").equals("string")) writer.write(comma + "\"" + value + "\""); else writer.write(comma + value); comma = ", "; } writer.write(");\n"); } Set allocatedMemberVariables = new HashSet(); // Store names as we go for reference /* Now capture names of constructor arguments */ Set constructorArguments = new HashSet(); // Store for names of constructor arguments { Vector args = constructor.getChildrenNamed("arg"); assert (DebugMsg.debugMsg( "ClassWriter", "ClassWriter::defineConstructor - getting " + args.size() + " arguments")); for (int i = 0; i < args.size(); i++) { IXMLElement arg = (IXMLElement) args.elementAt(i); String argName = XMLUtil.getAttribute(arg, "name"); constructorArguments.add(argName); } } Vector constructorAssignments = constructor.getChildrenNamed("assign"); Vector classVariables = klass.getChildrenNamed("var"); // Use the set below to track when an assignment is being made more than once for same variable Set assignmentsMade = new HashSet(); for (int i = 0; i < constructorAssignments.size(); i++) { IXMLElement element = (IXMLElement) constructorAssignments.elementAt(i); String target = XMLUtil.getAttribute(element, "name"); if (assignmentsMade.contains(target)) { writer.write("!ERROR: Duplicate assignment for " + target + "\n"); } else { assignmentsMade.add(target); // String type = getVariableType(classVariables, target); // trust in the parser, for it will assign the correct types String type = XMLUtil.getAttribute(element, "type"); IXMLElement sourceElement = element.getChildAtIndex(0); if (sourceElement.getName().equals("new")) { // Handle object allocation assert (DebugMsg.debugMsg( "ClassWriter", "ClassWriter::defineConstructor - allocating object for " + target)); String sourceType = XMLUtil.typeOf(sourceElement); writer.write(target + " = addVariable("); writer.write( sourceType + "Domain((new " + sourceType + "(m_id, \"" + target + "\"))->getId(), \"" + sourceType + "\")"); writer.write(", " + makeObjectVariableNameString(target) + ");\n"); writer.write( "Id<" + type + ">(singleton(" + target + "))->constructor(" + buildArguments( classVariables, constructorArguments, allocatedMemberVariables, sourceElement) + ");\n"); // Invoke initialization writer.write( "Id<" + type + ">(singleton(" + target + "))->handleDefaults();\n"); // Default variable setup } else { // Handle variable allocation String value = ModelAccessor.getValue(sourceElement); if (sourceElement.getName().equals("id") && type.equals(NddlXmlStrings.x_string)) value = XMLUtil.escapeQuotes(value); else if (sourceElement.getName().equals(NddlXmlStrings.x_symbol) || XMLUtil.getAttribute(sourceElement, "type").equals(NddlXmlStrings.x_string)) value = "LabelStr(\"" + XMLUtil.escapeQuotes(value) + "\")"; else if (ModelAccessor.isNumericPrimitive(type) && !type.equals(NddlXmlStrings.x_boolean)) { // Set both bounds to singleton value value = value + ", " + value; } writer.write(target + " = addVariable("); if (allocatedMemberVariables.contains( value)) // If we are assigning one member to another, we obtain the base domain for it writer.write(value + "->baseDomain()"); else writer.write(ModelAccessor.getDomain(type) + "(" + value + ", \"" + type + "\")"); writer.write(", " + makeObjectVariableNameString(target) + ");\n"); } // Add member to the set allocatedMemberVariables.add(target); } } writer.unindent(); writer.write("}\n"); assert (DebugMsg.debugMsg("ClassWriter", "End ClassWriter::defineConstructor")); }