neilg 2003/07/03 08:19:31 Modified: java/src/org/apache/xerces/impl/xs XSAnnotationImpl.java SchemaGrammar.java java/src/org/apache/xerces/impl/xs/traversers XSDAbstractTraverser.java Log: expose annotations in the PSVI. Now the XSAnnotation implementation is complete (though probably not yet bug-free) Revision Changes Path 1.2 +76 -2 xml-xerces/java/src/org/apache/xerces/impl/xs/XSAnnotationImpl.java Index: XSAnnotationImpl.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/XSAnnotationImpl.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- XSAnnotationImpl.java 18 Jun 2003 03:05:07 -0000 1.1 +++ XSAnnotationImpl.java 3 Jul 2003 15:19:30 -0000 1.2 @@ -59,12 +59,39 @@ import org.apache.xerces.impl.xs.psvi.XSAnnotation; import org.apache.xerces.impl.xs.psvi.XSConstants; import org.apache.xerces.impl.xs.psvi.XSNamespaceItem; +import org.apache.xerces.parsers.SAXParser; +import org.apache.xerces.parsers.DOMParser; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.InputSource; +import org.w3c.dom.Node; +import org.w3c.dom.Element; +import org.w3c.dom.Document; +import java.io.StringReader; +import java.io.IOException; /** * This is an implementation of the XSAnnotation schema component. */ public class XSAnnotationImpl implements XSAnnotation { + // Data + + // the content of the annotation node, including all children, along + // with any non-schema attributes from its parent + private String fData = null; + + // the grammar which owns this annotation; we get parsers + // from here when we need them + private SchemaGrammar fGrammar = null; + + // constructors + public XSAnnotationImpl(String contents, SchemaGrammar grammar) { + fData = contents; + fGrammar = grammar; + } + /** * Write contents of the annotation to the specified DOM object. If the * specified <code>target</code> object is a DOM in-scope namespace @@ -81,6 +108,13 @@ */ public boolean writeAnnotation(Object target, short targetType) { + if(targetType == XSAnnotation.W3C_DOM_ELEMENT || targetType == XSAnnotation.W3C_DOM_DOCUMENT) { + writeToDOM((Node)target, targetType); + return true; + } else if (targetType == SAX_CONTENTHANDLER) { + writeToSAX((ContentHandler)target); + return true; + } return false; } @@ -88,7 +122,7 @@ * A text representation of annotation. */ public String getAnnotationString() { - return null; + return fData; } // XSObject methods @@ -118,12 +152,52 @@ } /** - * A namespace schema information itemcorresponding to the target + * A namespace schema information item corresponding to the target * namespace of the component, if it's globally declared; or null * otherwise. */ public XSNamespaceItem getNamespaceItem() { return null; + } + + // private methods + private synchronized void writeToSAX(ContentHandler handler) { + // nothing must go wrong with this parse... + SAXParser parser = fGrammar.getSAXParser(); + StringReader aReader = new StringReader(fData); + InputSource aSource = new InputSource(aReader); + parser.setContentHandler(handler); + try { + parser.parse(aSource); + } catch (SAXException e) { + // this should never happen! + // REVISIT: what to do with this?; should really not + // eat it... + } catch (IOException i) { + // ditto with above + } + } + + // this creates the new Annotation element as the first child + // of the Node + private synchronized void writeToDOM(Node target, short type){ + Document futureOwner = (type == XSAnnotation.W3C_DOM_ELEMENT)?target.getOwnerDocument():(Document)target; + DOMParser parser = fGrammar.getDOMParser(); + StringReader aReader = new StringReader(fData); + InputSource aSource = new InputSource(aReader); + try { + parser.parse(aSource); + } catch (SAXException e) { + // this should never happen! + // REVISIT: what to do with this?; should really not + // eat it... + } catch (IOException i) { + // ditto with above + } + Document aDocument = parser.getDocument(); + Element annotation = aDocument.getDocumentElement(); + Node newElem = futureOwner.importNode(annotation, true); + target.insertBefore(newElem, target.getFirstChild()); } } 1.31 +53 -2 xml-xerces/java/src/org/apache/xerces/impl/xs/SchemaGrammar.java Index: SchemaGrammar.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/SchemaGrammar.java,v retrieving revision 1.30 retrieving revision 1.31 diff -u -r1.30 -r1.31 --- SchemaGrammar.java 23 Jun 2003 16:35:21 -0000 1.30 +++ SchemaGrammar.java 3 Jul 2003 15:19:30 -0000 1.31 @@ -83,7 +83,12 @@ import org.apache.xerces.impl.xs.util.XSNamedMap4Types; import org.apache.xerces.impl.xs.util.XSNamedMapImpl; import org.apache.xerces.impl.xs.util.XSObjectListImpl; +import org.apache.xerces.impl.Constants; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.parsers.SAXParser; +import org.apache.xerces.parsers.IntegratedParserConfiguration; import org.apache.xerces.util.SymbolHash; +import org.apache.xerces.util.SymbolTable; import org.apache.xerces.xni.grammars.XMLGrammarDescription; import org.apache.xerces.xni.grammars.XSGrammar; @@ -125,6 +130,12 @@ // number of annotations declared int fNumAnnotations; + // symbol table for constructing parsers (annotation support) + private SymbolTable fSymbolTable = null; + // parsers for annotation support + private SAXParser fSAXParser = null; + private DOMParser fDOMParser = null; + // // Constructors // @@ -138,10 +149,13 @@ * @param targetNamespace * @param grammarDesc the XMLGrammarDescription corresponding to this objec * at the least a systemId should always be known. + * @param symbolTable needed for annotation support */ - public SchemaGrammar(String targetNamespace, XSDDescription grammarDesc) { + public SchemaGrammar(String targetNamespace, XSDDescription grammarDesc, + SymbolTable symbolTable) { fTargetNamespace = targetNamespace; fGrammarDescription = grammarDesc; + fSymbolTable = symbolTable; // REVISIT: do we know the numbers of the following global decls // when creating this grammar? If so, we can pass the numbers in, @@ -292,6 +306,14 @@ public synchronized void addDocument(Object document, String location) { // ignore } + + // annotation support + synchronized DOMParser getDOMParser() { + return null; + } + synchronized SAXParser getSAXParser() { + return null; + } } // Grammar methods @@ -735,6 +757,35 @@ */ public String getSchemaNamespace() { return fTargetNamespace; + } + + // annotation support + synchronized DOMParser getDOMParser() { + if (fDOMParser != null) return fDOMParser; + // REVISIT: when schema handles XML 1.1, will need to + // revisit this (and the practice of not prepending an XML decl to the annotation string + IntegratedParserConfiguration config = new IntegratedParserConfiguration(fSymbolTable); + // note that this should never produce errors or require + // entity resolution, so just a barebones configuration with + // a couple of feature set will do fine + config.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE, true); + config.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE, false); + fDOMParser = new DOMParser(config); + return fDOMParser; + } + + synchronized SAXParser getSAXParser() { + if (fSAXParser != null) return fSAXParser; + // REVISIT: when schema handles XML 1.1, will need to + // revisit this (and the practice of not prepending an XML decl to the annotation string + IntegratedParserConfiguration config = new IntegratedParserConfiguration(fSymbolTable); + // note that this should never produce errors or require + // entity resolution, so just a barebones configuration with + // a couple of feature set will do fine + config.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE, true); + config.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE, false); + fSAXParser = new SAXParser(config); + return fSAXParser; } /** 1.28 +67 -2 xml-xerces/java/src/org/apache/xerces/impl/xs/traversers/XSDAbstractTraverser.java Index: XSDAbstractTraverser.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/traversers/XSDAbstractTraverser.java,v retrieving revision 1.27 retrieving revision 1.28 diff -u -r1.27 -r1.28 --- XSDAbstractTraverser.java 23 Jun 2003 16:35:22 -0000 1.27 +++ XSDAbstractTraverser.java 3 Jul 2003 15:19:31 -0000 1.28 @@ -80,6 +80,8 @@ import org.apache.xerces.util.SymbolTable; import org.apache.xerces.xni.QName; import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.Text; /** * Class <code>XSDAbstractTraverser</code> serves as the base class for all @@ -141,6 +143,7 @@ Object[] attrValues = fAttrChecker.checkAttributes(annotationDecl, isGlobal, schemaDoc); fAttrChecker.returnAttrArray(attrValues, schemaDoc); + String contents = null; for (Element child = DOMUtil.getFirstChildElement(annotationDecl); child != null; child = DOMUtil.getNextSiblingElement(child)) { @@ -151,6 +154,11 @@ if (!((name.equals(SchemaSymbols.ELT_APPINFO)) || (name.equals(SchemaSymbols.ELT_DOCUMENTATION)))) { reportSchemaError("src-annotation", new Object[]{name}, child); + } else { // the annotation, as we currently know it, is a Text child + Node textContent = child.getFirstChild(); + if(textContent != null && textContent.getNodeType() == Node.TEXT_NODE) { + contents = ((Text)textContent).getData(); + } } // General Attribute Checking @@ -159,8 +167,46 @@ attrValues = fAttrChecker.checkAttributes(child, true, schemaDoc); fAttrChecker.returnAttrArray(attrValues, schemaDoc); } + // if contents was null, must have been some kind of error; + // nothing to contribute to PSVI + if (contents == null) return null; + + // find the grammar; fSchemaHandler must be known! + SchemaGrammar grammar = fSchemaHandler.getGrammar(schemaDoc.fTargetNamespace); + // fish out local attributes passed from parent + Vector annotationLocalAttrs = (Vector)parentAttrs[XSAttributeChecker.ATTIDX_NONSCHEMA]; + // optimize for case where there are no local attributes + if(annotationLocalAttrs != null && !annotationLocalAttrs.isEmpty()) { + StringBuffer localStrBuffer = new StringBuffer(64); + localStrBuffer.append(" "); + // Vector should contain rawname value pairs + int i=0; + while(i<annotationLocalAttrs.size()) { + localStrBuffer.append((String)annotationLocalAttrs.elementAt(i++)) + .append("=\""); + String value = (String)annotationLocalAttrs.elementAt(i++); + // search for pesky "s and >s within attr value: + value = processAttValue(value); + localStrBuffer.append(value) + .append("\""); + } + localStrBuffer.append(" "); + // and now splice it into place; immediately after the annotation token, for simplicity's sake + StringBuffer contentBuffer = new StringBuffer(contents.length() + localStrBuffer.length()); + int annotationTokenEnd = contents.indexOf(SchemaSymbols.ELT_ANNOTATION); + // annotation must occur somewhere or we're in big trouble... + if(annotationTokenEnd == -1) return null; + annotationTokenEnd += SchemaSymbols.ELT_ANNOTATION.length(); + contentBuffer.append(contents.substring(0,annotationTokenEnd)); + contentBuffer.append(localStrBuffer.toString()); + contentBuffer.append(contents.substring(annotationTokenEnd, contents.length())); + System.err.println("annotation is\n"+contentBuffer); + return new XSAnnotationImpl(contentBuffer.toString(), grammar); + } else { + System.err.println("annotation is\n"+contents); + return new XSAnnotationImpl(contents, grammar); + } - return null; } // the QName simple type used to resolve qnames @@ -586,5 +632,24 @@ particle.fMaxOccurs = max; return particle; + } + + // this is not terribly performant! + private static String processAttValue(String original) { + // normally, nothing will happen + StringBuffer newVal = new StringBuffer(original.length()); + for(int i=0; i<original.length(); i++) { + char currChar = original.charAt(i); + if(currChar == '"') { + newVal.append("""); + } else if (currChar == '>') { + newVal.append(">"); + } else if (currChar == '&') { + newVal.append("&"); + } else { + newVal.append(currChar); + } + } + return newVal.toString(); } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]