@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); } }
@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; }
@NbBundle.Messages({ "# {0} - attribute name", "ERR_lowercasePropertyName=Invalid property name: {0}. Property name, or the last component of a static property name must start with lowercase.", "# {0} - attribute name", "ERR_invalidReservedPropertyName=Unknown name in FXML reserved namespace: {0}", "# {0} - attribute qname", "# {1} - tag name", "ERR_unsupportedAttribute=Unsupported attribute {0} on {1}" }) private void processInstanceAttributes(Attributes atts) { for (int i = 0; i < atts.getLength(); i++) { String uri = atts.getURI(i); String name = atts.getLocalName(i); String qname = atts.getQName(i); PropertySetter ps = null; FxNode node; if (qname.startsWith("xmlns")) { // NOI18N // FIXME - xmlns attributes will be represented as FxNodes :-/ continue; } if (FXML_FX_NAMESPACE.equals(uri)) { if (!(FX_ID.equals(name) || FX_CONTROLLER.equals(name) || FX_VALUE.equals(name) || FX_FACTORY.contains(name))) { addAttributeError( qname, "error-unsupported-attribute", ERR_unsupportedAttribute(qname, tagName), qname, tagName); } continue; } if (current instanceof FxInstanceCopy) { if (FxXmlSymbols.FX_ATTR_REFERENCE_SOURCE.equals(name) && uri == null) { // ignore source in fx:copy continue; } } // if the name begins with "on", it's an event handler. if (name.startsWith(EVENT_HANDLER_PREFIX) && name.length() > EVENT_HANDLER_PREFIX_LEN) { String en = Character.toLowerCase(name.charAt(EVENT_HANDLER_PREFIX_LEN)) + name.substring(EVENT_HANDLER_PREFIX_LEN + 1); node = processEventHandlerAttribute(en, atts.getValue(i)); // special hack for fx:copy or fx:reference } else { // FIXME - error detection for static property int stProp = FxXmlSymbols.findStaticProperty(name); if (stProp == -2) { // report error, not a well formed property name. addAttributeError(qname, "invalid-property-name", ERR_lowercasePropertyName(name), name); node = accessor.makeBroken(accessor.createProperty(name, false)); } else if (stProp == -1) { // this is a normal property node = ps = accessor.createProperty(name, false); } else { // it is a static property node = ps = accessor.createStaticProperty( name.substring(stProp + 1), name.substring(0, stProp)); } if (ps != null) { accessor.addContent(ps, atts.getValue(i)); node = ps; } } initAttribute(node, qname); attachProperty(ps); attachChildNode(node); } }
@NbBundle.Messages({ "# {0} - tag name", "ERR_tagNotJavaIdentifier=Invalid class name: {0}", "# {0} - tag name", "ERR_fxControllerPermittedOnRoot=fx:controller is not permitted on tag {0}. Can be only present on root element." }) private FxNewInstance handleClassTag(String localName, Attributes atts) { String fxValueContent = null; String fxFactoryContent = null; String fxId = null; int off = contentLocator.getElementOffset() + 1; // the < for (int i = 0; i < atts.getLength(); i++) { String uri = atts.getURI(i); if (!FXML_FX_NAMESPACE.equals(uri)) { // no special attribute continue; } String name = atts.getLocalName(i); if (FX_VALUE.equals(name)) { fxValueContent = atts.getValue(i); } else if (FX_FACTORY.equals(name)) { fxFactoryContent = atts.getValue(i); } else if (FX_ID.equals(name)) { fxId = atts.getValue(i); } else if (FX_CONTROLLER.equals(name)) { if (nodeStack.peek().getKind() != Kind.Source) { addAttributeError( atts.getQName(i), "fx-controller-permitted-on-root", ERR_fxControllerPermittedOnRoot(localName), localName); } else { controllerName = atts.getValue(i); } } else { addAttributeError( atts.getQName(i), "invalid-property-reserved-name", ERR_invalidReservedPropertyName(name), name); } } // first we must check how this class tag is created. FxNewInstance instance = accessor.createInstance(localName, fxValueContent, fxFactoryContent, fxId); if (!FxXmlSymbols.isQualifiedIdentifier(localName)) { // not a java identifier, error addError( new ErrorMark( off, localName.length(), "invalid-class-name", ERR_tagNotJavaIdentifier(localName), localName)); accessor.makeBroken(instance); return instance; } return instance; }