@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); }
@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); } }
private ErrorMark addError(String errCode, String message, Object... params) { int offs = contentLocator.getElementOffset(); ErrorMark m = new ErrorMark(offs, contentLocator.getEndOffset() - offs, errCode, message, params); addError(m); return m; }
@Override public void characterSequence(CharSequence seq) { addElementErrors(); int length = seq.length(); FxNode node = nodeStack.peek(); FxNode addedNode = null; switch (node.getKind()) { case Event: addedNode = handleEventContent(seq); break; case Instance: addedNode = handleInstanceContent(seq); break; case Property: addedNode = handlePropertyContent(seq); break; default: addError( new ErrorMark( contentLocator.getElementOffset(), length, "unexpected-characters", ERR_unexpectedCharacters())); } if (addedNode != null) { i(addedNode).endsAt(contentLocator.getEndOffset()); } }
@NbBundle.Messages({ "# {0} - PI target", "ERR_invalidProcessingInstruction=Invalid processing instruction: {0}. Expected 'import', 'include' or 'language'", "ERR_missingProcessingInstruction=Missing processing intruction." }) private void handleErrorInstruction(String target, String data) { int start = contentLocator.getElementOffset(); int offset = -1; int piOffset = -1; TokenSequence<XMLTokenId> seq = contentLocator.getTokenSequence(); // lex up to the invalid target: seq.move(start); boolean found = false; while (!found && seq.moveNext()) { Token<XMLTokenId> t = seq.token(); switch (t.id()) { case PI_START: piOffset = offset; if (target == null) { found = true; } case WS: break; default: case PI_TARGET: offset = seq.offset(); found = true; break; } } ErrorMark mark; if (target != null) { mark = new ErrorMark( offset, seq.token().length(), "invalid-processing-instruction", ERR_invalidProcessingInstruction(target), target); } else { mark = new ErrorMark( piOffset, seq.token().length(), "missing-processing-instruction", ERR_missingProcessingInstruction()); } addError(mark); }
@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 void initAttribute(FxNode node, String atQName) { NodeInfo ni = i(node); ni.makeAttribute(); int[] offsets = contentLocator.getAttributeOffsets(atQName); ni.startAt(offsets[ContentLocator.OFFSET_START]) .endsAt(offsets[ContentLocator.OFFSET_END]) .startContent(offsets[ContentLocator.OFFSET_VALUE_START]) .endContent(offsets[ContentLocator.OFFSET_VALUE_END]); }
@Override public void endElement(String uri, String localName, String qName) throws SAXException { addElementErrors(); FxNode node = nodeStack.pop(); i(node).endsAt(contentLocator.getEndOffset()).endContent(contentLocator.getElementOffset()); if (node instanceof PropertySetter) { PropertySetter s = (PropertySetter) node; if (s.isImplicit()) { // actually the outer element ends node = nodeStack.pop(); // copy the offset information i(node).endsAt(contentLocator.getEndOffset()).endContent(contentLocator.getElementOffset()); } } String tn = node.getSourceName(); if (!tn.equals(localName)) { throw new IllegalStateException(); } // special hack for parent nodes, which are implicit property setters: FxNode parentNode = nodeStack.peek(); if (parentNode instanceof PropertySetter) { PropertySetter ps = (PropertySetter) parentNode; if (ps.isImplicit() && ps.getContent() == null) { i(ps).endsAt(contentLocator.getEndOffset()).endContent(contentLocator.getEndOffset()); } } if (!nodeStack.isEmpty() && nodeStack.peek().getKind() == Kind.Instance) { current = (FxInstance) nodeStack.peek(); } else { current = null; } }
private void addAttributeError(String qName, String code, String message, Object... params) { int[] offsets = contentLocator.getAttributeOffsets(qName); int s; if (offsets == null) { FxNode n = nodeStack.peek(); if (n != null) { s = i(n).getStart(); } else { s = -1; } } else { s = offsets[ContentLocator.OFFSET_START]; } addError(new ErrorMark(s, qName.length(), code, message, params)); }
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} - 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; }
private void initElement(FxNode node) { NodeInfo ni = i(node); ni.startAt(contentLocator.getElementOffset()).startContent(contentLocator.getEndOffset()); ni.setTagName(tagName); }
void addElementErrors() { this.errors.addAll(contentLocator.getErrors()); }