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]