@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; }
/** * 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 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; }
/** * Checks that the instance is allowed in this context. May even create e.g. default property * setter etc. Will return true, if the instance can be attached to the parent. */ @NbBundle.Messages({ "# {0} - tag name", "ERR_moreRootElements=Duplicate root element: {0}", "ERR_instanceInMapProperty=Cannot add instances directly to readonly Map", "# {0} - parent tag name", "ERR_parentNotSupportInstance=Instances cannot be added to the parent {0}" }) private FxNode attachInstance(FxObjectBase instance) { String localName = instance.getSourceName(); int off = contentLocator.getElementOffset() + 1; // check the parent, whether it is appropriate to host such a node: FxNode parent = nodeStack.peek(); if (parent.getKind() == Kind.Instance) { // pretend we have a default property PropertySetter s = accessor.createProperty(null, true); i(s).startAt(contentLocator.getElementOffset()); attachChildNode(s); parent = s; } if (parent.getKind() == Kind.Source) { FxObjectBase old = rootComponent; if (old != null) { addError( new ErrorMark( off, contentLocator.getEndOffset() - off, "duplicate-root", ERR_moreRootElements(localName), localName)); accessor.makeBroken(instance); } else if (!(instance instanceof FxInstance)) { // FIXME - report error that fx:reference is not accepted on root element throw new UnsupportedOperationException(); } else { rootComponent = (FxInstance) instance; } } else if (parent.getKind() == Kind.Property) { if (parent instanceof MapProperty) { addError( new ErrorMark( off, contentLocator.getEndOffset() - off, "instance-in-map-property", ERR_instanceInMapProperty(), localName)); accessor.makeBroken(instance); } } else if (parent.getKind() == Kind.Element && parent.getSourceName().equals(FxXmlSymbols.FX_DEFINITIONS) && (instance instanceof FxNewInstance)) { instanceDefinitions.add((FxNewInstance) instance); } else { if (parent.getKind() != Kind.Error) { addError( new ErrorMark( off, contentLocator.getEndOffset() - off, "parent-not-support-instance", ERR_parentNotSupportInstance(parent.getSourceName()))); accessor.makeBroken(instance); } } return instance; }
@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); } }