element.
+ match = ( elem instanceof HTMLTableCellElement );
+ break;
+ }
+
+ // If element type was matched and a name was specified, must also match
+ // the name against either the 'id' or the 'name' attribute. The 'name'
+ // attribute is relevant only for elements for backward compatibility.
+ if ( match && name != null )
+ {
+ // If an anchor and 'name' attribute matches, return true. Otherwise,
+ // try 'id' attribute.
+ if ( elem instanceof HTMLAnchorElement &&
+ name.equals( elem.getAttribute( "name" ) ) )
+ return true;
+ match = name.equals( elem.getAttribute( "id" ) );
+ }
+ }
+ return match;
+ }
+
+
+}
+
+
+/**
+ * {@link CollectionImpl#item} must traverse down the tree and decrement the
+ * index until it matches an element who's index is zero. Since integers are
+ * passed by value, this class servers to pass the index into each recursion
+ * by reference. It encompasses all the operations that need be performed on
+ * the index, although direct access is possible.
+ *
+ * @xerces.internal
+ *
+ * @see CollectionImpl#item
+ */
+class CollectionIndex
+{
+
+
+ /**
+ * Returns the current index.
+ *
+ * @return Current index
+ */
+ int getIndex()
+ {
+ return _index;
+ }
+
+
+ /**
+ * Decrements the index by one.
+ */
+ void decrement()
+ {
+ -- _index;
+ }
+
+
+ /**
+ * Returns true if index is zero (or negative).
+ *
+ * @return True if index is zero
+ */
+ boolean isZero()
+ {
+ return _index <= 0;
+ }
+
+
+ /**
+ * Constructs a new index with the specified initial value. The index will
+ * then be decremeneted until it reaches zero.
+ *
+ * @param index The initial value
+ */
+ CollectionIndex( int index )
+ {
+ _index = index;
+ }
+
+
+ /**
+ * Holds the actual value that is passed by reference using this class.
+ */
+ private int _index;
+
+
+}
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLDListElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLDListElementImpl.java
new file mode 100644
index 0000000..1174c83
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLDListElementImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLDListElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLDListElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLDListElementImpl
+ extends HTMLElementImpl
+ implements HTMLDListElement
+{
+
+ private static final long serialVersionUID = -2130005642453038604L;
+
+ public boolean getCompact()
+ {
+ return getBinary( "compact" );
+ }
+
+
+ public void setCompact( boolean compact )
+ {
+ setAttribute( "compact", compact );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLDListElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLDOMImplementationImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLDOMImplementationImpl.java
new file mode 100644
index 0000000..fb127a1
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLDOMImplementationImpl.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+
+import org.apache.xerces.dom.DOMImplementationImpl;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.html.HTMLDOMImplementation;
+import org.w3c.dom.html.HTMLDocument;
+
+
+/**
+ * Provides number of methods for performing operations that are independent
+ * of any particular instance of the document object model. This class is
+ * unconstructable, the only way to obtain an instance of a DOM implementation
+ * is by calling the static method {@link #getDOMImplementation}.
+ *
+ * @xerces.internal
+ *
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.DOMImplementation
+ */
+public class HTMLDOMImplementationImpl
+ extends DOMImplementationImpl
+ implements HTMLDOMImplementation
+{
+
+
+ /**
+ * Holds a reference to the single instance of the DOM implementation.
+ * Only one instance is required since this class is multiple entry.
+ */
+ private static final HTMLDOMImplementation _instance = new HTMLDOMImplementationImpl();
+
+
+ /**
+ * Private constructor assures that an object of this class cannot
+ * be created. The only way to obtain an object is by calling {@link
+ * #getDOMImplementation}.
+ */
+ private HTMLDOMImplementationImpl()
+ {
+ }
+
+
+ /**
+ * Create a new HTML document of the specified TITLE text.
+ *
+ * @param title The document title text
+ * @return New HTML document
+ */
+ public final HTMLDocument createHTMLDocument( String title )
+ throws DOMException
+ {
+ HTMLDocument doc;
+
+ if ( title == null )
+ throw new NullPointerException( "HTM014 Argument 'title' is null." );
+ doc = new HTMLDocumentImpl();
+ doc.setTitle( title );
+ return doc;
+ }
+
+
+ /**
+ * Returns an instance of a {@link HTMLDOMImplementation} that can be
+ * used to perform operations that are not specific to a particular
+ * document instance, e.g. to create a new document.
+ *
+ * @return Reference to a valid DOM implementation
+ */
+ public static HTMLDOMImplementation getHTMLDOMImplementation()
+ {
+ return _instance;
+ }
+
+
+}
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLDirectoryElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLDirectoryElementImpl.java
new file mode 100644
index 0000000..b556b89
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLDirectoryElementImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLDirectoryElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLDirectoryElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLDirectoryElementImpl
+ extends HTMLElementImpl
+ implements HTMLDirectoryElement
+{
+
+ private static final long serialVersionUID = -1010376135190194454L;
+
+ public boolean getCompact()
+ {
+ return getBinary( "compact" );
+ }
+
+
+ public void setCompact( boolean compact )
+ {
+ setAttribute( "compact", compact );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLDirectoryElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLDivElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLDivElementImpl.java
new file mode 100644
index 0000000..ad781c1
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLDivElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLDivElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLDivElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLDivElementImpl
+ extends HTMLElementImpl
+ implements HTMLDivElement
+{
+
+ private static final long serialVersionUID = 2327098984177358833L;
+
+ public String getAlign()
+ {
+ return capitalize( getAttribute( "align" ) );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLDivElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLDocumentImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLDocumentImpl.java
new file mode 100644
index 0000000..20f484d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLDocumentImpl.java
@@ -0,0 +1,788 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.html.dom;
+
+import java.io.StringWriter;
+import java.lang.reflect.Constructor;
+import java.util.Hashtable;
+import java.util.Locale;
+
+import org.apache.xerces.dom.DocumentImpl;
+import org.apache.xerces.dom.ElementImpl;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.UserDataHandler;
+import org.w3c.dom.html.HTMLBodyElement;
+import org.w3c.dom.html.HTMLCollection;
+import org.w3c.dom.html.HTMLDocument;
+import org.w3c.dom.html.HTMLElement;
+import org.w3c.dom.html.HTMLFrameSetElement;
+import org.w3c.dom.html.HTMLHeadElement;
+import org.w3c.dom.html.HTMLHtmlElement;
+import org.w3c.dom.html.HTMLTitleElement;
+
+/**
+ * Implements an HTML document. Provides access to the top level element in the
+ * document, its body and title.
+ *
+ * Several methods create new nodes of all basic types (comment, text, element,
+ * etc.). These methods create new nodes but do not place them in the document
+ * tree. The nodes may be placed in the document tree using {@link
+ * org.w3c.dom.Node#appendChild} or {@link org.w3c.dom.Node#insertBefore}, or
+ * they may be placed in some other document tree.
+ *
+ * Note: <FRAMESET> documents are not supported at the moment, neither
+ * are direct document writing ({@link #open}, {@link #write}) and HTTP attribute
+ * methods ({@link #getURL}, {@link #getCookie}).
+ *
+ * @xerces.internal
+ *
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLDocument
+ */
+public class HTMLDocumentImpl
+ extends DocumentImpl
+ implements HTMLDocument
+{
+
+ private static final long serialVersionUID = 4285791750126227180L;
+
+ /**
+ * Holds HTMLCollectionImpl object with live collection of all
+ * anchors in document. This reference is on demand only once.
+ */
+ private HTMLCollectionImpl _anchors;
+
+
+ /**
+ * Holds HTMLCollectionImpl object with live collection of all
+ * forms in document. This reference is on demand only once.
+ */
+ private HTMLCollectionImpl _forms;
+
+
+ /**
+ * Holds HTMLCollectionImpl object with live collection of all
+ * images in document. This reference is on demand only once.
+ */
+ private HTMLCollectionImpl _images;
+
+
+ /**
+ * Holds HTMLCollectionImpl object with live collection of all
+ * links in document. This reference is on demand only once.
+ */
+ private HTMLCollectionImpl _links;
+
+
+ /**
+ * Holds HTMLCollectionImpl object with live collection of all
+ * applets in document. This reference is on demand only once.
+ */
+ private HTMLCollectionImpl _applets;
+
+
+ /**
+ * Holds string writer used by direct manipulation operation ({@link #open}.
+ * {@link #write}, etc) to write new contents into the document and parse
+ * that text into a document tree.
+ */
+ private StringWriter _writer;
+
+
+ /**
+ * Holds names and classes of HTML element types. When an element with a
+ * particular tag name is created, the matching {@link java.lang.Class}
+ * is used to create the element object. For example, <A> matches
+ * {@link HTMLAnchorElementImpl}. This static table is shared across all
+ * HTML documents.
+ *
+ * @see #createElement
+ */
+ private static Hashtable _elementTypesHTML;
+
+
+ /**
+ * Signature used to locate constructor of HTML element classes. This
+ * static array is shared across all HTML documents.
+ *
+ * @see #createElement
+ */
+ private static final Class[] _elemClassSigHTML =
+ new Class[] { HTMLDocumentImpl.class, String.class };
+
+
+ /**
+ */
+ public HTMLDocumentImpl()
+ {
+ super();
+ populateElementTypes();
+ }
+
+
+ public synchronized Element getDocumentElement()
+ {
+ Node html;
+ Node child;
+ Node next;
+
+ // The document element is the top-level HTML element of the HTML
+ // document. Only this element should exist at the top level.
+ // If the HTML element is found, all other elements that might
+ // precede it are placed inside the HTML element.
+ html = getFirstChild();
+ while ( html != null )
+ {
+ if ( html instanceof HTMLHtmlElement )
+ {
+ // REVISIT: [Q] Why is this code even here? In fact, the
+ // original code is in error because it will
+ // try to move ALL nodes to be children of the
+ // HTML tag. This is not the intended behavior
+ // for comments and processing instructions
+ // outside the root element; it will throw a
+ // hierarchy request error exception for doctype
+ // nodes; *and* this code shouldn't even be
+ // needed because the parser should never build
+ // a document that contains more than a single
+ // root element, anyway! -Ac
+ /***
+ synchronized ( html )
+ {
+ child = getFirstChild();
+ while ( child != null && child != html )
+ {
+ next = child.getNextSibling();
+ html.appendChild( child );
+ child = next;
+ }
+ }
+ /***/
+ return (HTMLElement) html;
+ }
+ html = html.getNextSibling();
+ }
+
+ // HTML element must exist. Create a new element and dump the
+ // entire contents of the document into it in the same order as
+ // they appear now.
+ html = new HTMLHtmlElementImpl( this, "HTML" );
+ child = getFirstChild();
+ while ( child != null )
+ {
+ next = child.getNextSibling();
+ html.appendChild( child );
+ child = next;
+ }
+ appendChild( html );
+ return (HTMLElement) html;
+ }
+
+
+ /**
+ * Obtains the <HEAD> element in the document, creating one if does
+ * not exist before. The <HEAD> element is the first element in the
+ * <HTML> in the document. The <HTML> element is obtained by
+ * calling {@link #getDocumentElement}. If the element does not exist, one
+ * is created.
+ *
+ * Called by {@link #getTitle}, {@link #setTitle}, {@link #getBody} and
+ * {@link #setBody} to assure the document has the <HEAD> element
+ * correctly placed.
+ *
+ * @return The <HEAD> element
+ */
+ public synchronized HTMLElement getHead()
+ {
+ Node head;
+ Node html;
+ Node child;
+ Node next;
+
+ // Call getDocumentElement() to get the HTML element that is also the
+ // top-level element in the document. Get the first element in the
+ // document that is called HEAD. Work with that.
+ html = getDocumentElement();
+ synchronized ( html )
+ {
+ head = html.getFirstChild();
+ while ( head != null && ! ( head instanceof HTMLHeadElement ) )
+ head = head.getNextSibling();
+ // HEAD exists but might not be first element in HTML: make sure
+ // it is and return it.
+ if ( head != null )
+ {
+ synchronized ( head )
+ {
+ child = html.getFirstChild();
+ while ( child != null && child != head )
+ {
+ next = child.getNextSibling();
+ head.insertBefore( child, head.getFirstChild() );
+ child = next;
+ }
+ }
+ return (HTMLElement) head;
+ }
+
+ // Head does not exist, create a new one, place it at the top of the
+ // HTML element and return it.
+ head = new HTMLHeadElementImpl( this, "HEAD" );
+ html.insertBefore( head, html.getFirstChild() );
+ }
+ return (HTMLElement) head;
+ }
+
+
+ public synchronized String getTitle()
+ {
+ HTMLElement head;
+ NodeList list;
+ Node title;
+
+ // Get the HEAD element and look for the TITLE element within.
+ // When found, make sure the TITLE is a direct child of HEAD,
+ // and return the title's text (the Text node contained within).
+ head = getHead();
+ list = head.getElementsByTagName( "TITLE" );
+ if ( list.getLength() > 0 ) {
+ title = list.item( 0 );
+ return ( (HTMLTitleElement) title ).getText();
+ }
+ // No TITLE found, return an empty string.
+ return "";
+ }
+
+
+ public synchronized void setTitle( String newTitle )
+ {
+ HTMLElement head;
+ NodeList list;
+ Node title;
+
+ // Get the HEAD element and look for the TITLE element within.
+ // When found, make sure the TITLE is a direct child of HEAD,
+ // and set the title's text (the Text node contained within).
+ head = getHead();
+ list = head.getElementsByTagName( "TITLE" );
+ if ( list.getLength() > 0 ) {
+ title = list.item( 0 );
+ if ( title.getParentNode() != head )
+ head.appendChild( title );
+ ( (HTMLTitleElement) title ).setText( newTitle );
+ }
+ else
+ {
+ // No TITLE found, create a new element and place it at the end
+ // of the HEAD element.
+ title = new HTMLTitleElementImpl( this, "TITLE" );
+ ( (HTMLTitleElement) title ).setText( newTitle );
+ head.appendChild( title );
+ }
+ }
+
+
+ public synchronized HTMLElement getBody()
+ {
+ Node html;
+ Node head;
+ Node body;
+ Node child;
+ Node next;
+
+ // Call getDocumentElement() to get the HTML element that is also the
+ // top-level element in the document. Get the first element in the
+ // document that is called BODY. Work with that.
+ html = getDocumentElement();
+ head = getHead();
+ synchronized ( html )
+ {
+ body = head.getNextSibling();
+ while ( body != null && ! ( body instanceof HTMLBodyElement )
+ && ! ( body instanceof HTMLFrameSetElement ) )
+ body = body.getNextSibling();
+
+ // BODY/FRAMESET exists but might not be second element in HTML
+ // (after HEAD): make sure it is and return it.
+ if ( body != null )
+ {
+ synchronized ( body )
+ {
+ child = head.getNextSibling();
+ while ( child != null && child != body )
+ {
+ next = child.getNextSibling();
+ body.insertBefore( child, body.getFirstChild() );
+ child = next;
+ }
+ }
+ return (HTMLElement) body;
+ }
+
+ // BODY does not exist, create a new one, place it in the HTML element
+ // right after the HEAD and return it.
+ body = new HTMLBodyElementImpl( this, "BODY" );
+ html.appendChild( body );
+ }
+ return (HTMLElement) body;
+ }
+
+
+ public synchronized void setBody( HTMLElement newBody )
+ {
+ Node html;
+ Node body;
+ Node head;
+ Node child;
+ NodeList list;
+
+ synchronized ( newBody )
+ {
+ // Call getDocumentElement() to get the HTML element that is also the
+ // top-level element in the document. Get the first element in the
+ // document that is called BODY. Work with that.
+ html = getDocumentElement();
+ head = getHead();
+ synchronized ( html )
+ {
+ list = this.getElementsByTagName( "BODY" );
+ if ( list.getLength() > 0 ) {
+ // BODY exists but might not follow HEAD in HTML. If not,
+ // make it so and replce it. Start with the HEAD and make
+ // sure the BODY is the first element after the HEAD.
+ body = list.item( 0 );
+ synchronized ( body )
+ {
+ child = head;
+ while ( child != null )
+ {
+ if ( child instanceof Element )
+ {
+ if ( child != body )
+ html.insertBefore( newBody, child );
+ else
+ html.replaceChild( newBody, body );
+ return;
+ }
+ child = child.getNextSibling();
+ }
+ html.appendChild( newBody );
+ }
+ return;
+ }
+ // BODY does not exist, place it in the HTML element
+ // right after the HEAD.
+ html.appendChild( newBody );
+ }
+ }
+ }
+
+
+ public synchronized Element getElementById( String elementId )
+ {
+ Element idElement = super.getElementById(elementId);
+ if (idElement != null) {
+ return idElement;
+ }
+ return getElementById( elementId, this );
+ }
+
+
+ public NodeList getElementsByName( String elementName )
+ {
+ return new NameNodeListImpl( this, elementName );
+ }
+
+
+ public final NodeList getElementsByTagName( String tagName )
+ {
+ return super.getElementsByTagName( tagName.toUpperCase(Locale.ENGLISH) );
+ }
+
+
+ public final NodeList getElementsByTagNameNS( String namespaceURI,
+ String localName )
+ {
+ if ( namespaceURI != null && namespaceURI.length() > 0 ) {
+ return super.getElementsByTagNameNS( namespaceURI, localName.toUpperCase(Locale.ENGLISH) );
+ }
+ return super.getElementsByTagName( localName.toUpperCase(Locale.ENGLISH) );
+ }
+
+
+ /**
+ * Xerces-specific constructor. "localName" is passed in, so we don't need
+ * to create a new String for it.
+ *
+ * @param namespaceURI The namespace URI of the element to
+ * create.
+ * @param qualifiedName The qualified name of the element type to
+ * instantiate.
+ * @param localpart The local name of the element to instantiate.
+ * @return Element A new Element object with the following attributes:
+ * @throws DOMException INVALID_CHARACTER_ERR: Raised if the specified
+ * name contains an invalid character.
+ */
+ public Element createElementNS(String namespaceURI, String qualifiedName,
+ String localpart)
+ throws DOMException
+ {
+ return createElementNS(namespaceURI, qualifiedName);
+ }
+
+ public Element createElementNS( String namespaceURI, String qualifiedName )
+ {
+ if ( namespaceURI == null || namespaceURI.length() == 0 ) {
+ return createElement( qualifiedName );
+ }
+ return super.createElementNS( namespaceURI, qualifiedName );
+ }
+
+
+ public Element createElement( String tagName )
+ throws DOMException
+ {
+ Class elemClass;
+ Constructor cnst;
+
+ // First, make sure tag name is all upper case, next get the associated
+ // element class. If no class is found, generate a generic HTML element.
+ // Do so also if an unexpected exception occurs.
+ tagName = tagName.toUpperCase(Locale.ENGLISH);
+ elemClass = (Class) _elementTypesHTML.get( tagName );
+ if ( elemClass != null )
+ {
+ // Get the constructor for the element. The signature specifies an
+ // owner document and a tag name. Use the constructor to instantiate
+ // a new object and return it.
+ try
+ {
+ cnst = elemClass.getConstructor( _elemClassSigHTML );
+ return (Element) cnst.newInstance( new Object[] { this, tagName } );
+ }
+ catch ( Exception except )
+ {
+ /*
+ Throwable thrw;
+
+ if ( except instanceof java.lang.reflect.InvocationTargetException )
+ thrw = ( (java.lang.reflect.InvocationTargetException) except ).getTargetException();
+ else
+ thrw = except;
+ System.out.println( "Exception " + thrw.getClass().getName() );
+ System.out.println( thrw.getMessage() );
+ */
+ throw new IllegalStateException( "HTM15 Tag '" + tagName + "' associated with an Element class that failed to construct.\n" + tagName);
+ }
+ }
+ return new HTMLElementImpl( this, tagName );
+ }
+
+
+ /**
+ * Creates an Attribute having this Document as its OwnerDoc.
+ * Overrides {@link DocumentImpl#createAttribute} and returns
+ * and attribute whose name is lower case.
+ *
+ * @param name The name of the attribute
+ * @return An attribute whose name is all lower case
+ * @throws DOMException(INVALID_NAME_ERR) if the attribute name
+ * is not acceptable
+ */
+ public Attr createAttribute( String name )
+ throws DOMException
+ {
+ return super.createAttribute( name.toLowerCase(Locale.ENGLISH) );
+ }
+
+
+ public String getReferrer()
+ {
+ // Information not available on server side.
+ return null;
+ }
+
+
+ public String getDomain()
+ {
+ // Information not available on server side.
+ return null;
+ }
+
+
+ public String getURL()
+ {
+ // Information not available on server side.
+ return null;
+ }
+
+
+ public String getCookie()
+ {
+ // Information not available on server side.
+ return null;
+ }
+
+
+ public void setCookie( String cookie )
+ {
+ // Information not available on server side.
+ }
+
+
+ public HTMLCollection getImages()
+ {
+ // For more information see HTMLCollection#collectionMatch
+ if ( _images == null )
+ _images = new HTMLCollectionImpl( getBody(), HTMLCollectionImpl.IMAGE );
+ return _images;
+ }
+
+
+ public HTMLCollection getApplets()
+ {
+ // For more information see HTMLCollection#collectionMatch
+ if ( _applets == null )
+ _applets = new HTMLCollectionImpl( getBody(), HTMLCollectionImpl.APPLET );
+ return _applets;
+ }
+
+
+ public HTMLCollection getLinks()
+ {
+ // For more information see HTMLCollection#collectionMatch
+ if ( _links == null )
+ _links = new HTMLCollectionImpl( getBody(), HTMLCollectionImpl.LINK );
+ return _links;
+ }
+
+
+ public HTMLCollection getForms()
+ {
+ // For more information see HTMLCollection#collectionMatch
+ if ( _forms == null )
+ _forms = new HTMLCollectionImpl( getBody(), HTMLCollectionImpl.FORM );
+ return _forms;
+ }
+
+
+ public HTMLCollection getAnchors()
+ {
+ // For more information see HTMLCollection#collectionMatch
+ if ( _anchors == null )
+ _anchors = new HTMLCollectionImpl( getBody(), HTMLCollectionImpl.ANCHOR );
+ return _anchors;
+ }
+
+
+ public void open()
+ {
+ // When called an in-memory is prepared. The document tree is still
+ // accessible the old way, until this writer is closed.
+ if ( _writer == null )
+ _writer = new StringWriter();
+ }
+
+
+ public void close()
+ {
+ // ! NOT IMPLEMENTED, REQUIRES PARSER !
+ if ( _writer != null )
+ {
+ _writer = null;
+ }
+ }
+
+
+ public void write( String text )
+ {
+ // Write a string into the in-memory writer.
+ if ( _writer != null )
+ _writer.write( text );
+ }
+
+
+ public void writeln( String text )
+ {
+ // Write a line into the in-memory writer.
+ if ( _writer != null )
+ _writer.write( text + "\n" );
+ }
+
+
+ public Node cloneNode( boolean deep )
+ {
+ HTMLDocumentImpl newdoc = new HTMLDocumentImpl();
+ callUserDataHandlers(this, newdoc, UserDataHandler.NODE_CLONED);
+ cloneNode(newdoc, deep);
+ return newdoc;
+ }
+
+
+ /* (non-Javadoc)
+ * @see CoreDocumentImpl#canRenameElements()
+ */
+ protected boolean canRenameElements(String newNamespaceURI, String newNodeName, ElementImpl el) {
+ if (el.getNamespaceURI() != null) {
+ // element is not HTML:
+ // can be renamed if not changed to HTML
+ return newNamespaceURI != null;
+ }
+
+ // check whether a class change is required
+ Class newClass = (Class) _elementTypesHTML.get(newNodeName.toUpperCase(Locale.ENGLISH));
+ Class oldClass = (Class) _elementTypesHTML.get(el.getTagName());
+ return newClass == oldClass;
+ }
+
+
+ /**
+ * Recursive method retreives an element by its id attribute.
+ * Called by {@link #getElementById(String)}.
+ *
+ * @param elementId The id value to look for
+ * @return The node in which to look for
+ */
+ private Element getElementById( String elementId, Node node )
+ {
+ Node child;
+ Element result;
+
+ child = node.getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof Element )
+ {
+ if ( elementId.equals( ( (Element) child ).getAttribute( "id" ) ) )
+ return (Element) child;
+ result = getElementById( elementId, child );
+ if ( result != null )
+ return result;
+ }
+ child = child.getNextSibling();
+ }
+ return null;
+ }
+
+
+ /**
+ * Called by the constructor to populate the element types list (see {@link
+ * #_elementTypesHTML}). Will be called multiple times but populate the list
+ * only the first time. Replacement for static constructor.
+ */
+ private synchronized static void populateElementTypes()
+ {
+ // This class looks like it is due to some strange
+ // (read: inconsistent) JVM bugs.
+ // Initially all this code was placed in the static constructor,
+ // but that caused some early JVMs (1.1) to go mad, and if a
+ // class could not be found (as happened during development),
+ // the JVM would die.
+ // Bertrand Delacretaz pointed out
+ // several configurations where HTMLAnchorElementImpl.class
+ // failed, forcing me to revert back to Class.forName().
+
+ if ( _elementTypesHTML != null )
+ return;
+ _elementTypesHTML = new Hashtable( 63 );
+ populateElementType( "A", "HTMLAnchorElementImpl" );
+ populateElementType( "APPLET", "HTMLAppletElementImpl" );
+ populateElementType( "AREA", "HTMLAreaElementImpl" );
+ populateElementType( "BASE", "HTMLBaseElementImpl" );
+ populateElementType( "BASEFONT", "HTMLBaseFontElementImpl" );
+ populateElementType( "BLOCKQUOTE", "HTMLQuoteElementImpl" );
+ populateElementType( "BODY", "HTMLBodyElementImpl" );
+ populateElementType( "BR", "HTMLBRElementImpl" );
+ populateElementType( "BUTTON", "HTMLButtonElementImpl" );
+ populateElementType( "DEL", "HTMLModElementImpl" );
+ populateElementType( "DIR", "HTMLDirectoryElementImpl" );
+ populateElementType( "DIV", "HTMLDivElementImpl" );
+ populateElementType( "DL", "HTMLDListElementImpl" );
+ populateElementType( "FIELDSET", "HTMLFieldSetElementImpl" );
+ populateElementType( "FONT", "HTMLFontElementImpl" );
+ populateElementType( "FORM", "HTMLFormElementImpl" );
+ populateElementType( "FRAME","HTMLFrameElementImpl" );
+ populateElementType( "FRAMESET", "HTMLFrameSetElementImpl" );
+ populateElementType( "HEAD", "HTMLHeadElementImpl" );
+ populateElementType( "H1", "HTMLHeadingElementImpl" );
+ populateElementType( "H2", "HTMLHeadingElementImpl" );
+ populateElementType( "H3", "HTMLHeadingElementImpl" );
+ populateElementType( "H4", "HTMLHeadingElementImpl" );
+ populateElementType( "H5", "HTMLHeadingElementImpl" );
+ populateElementType( "H6", "HTMLHeadingElementImpl" );
+ populateElementType( "HR", "HTMLHRElementImpl" );
+ populateElementType( "HTML", "HTMLHtmlElementImpl" );
+ populateElementType( "IFRAME", "HTMLIFrameElementImpl" );
+ populateElementType( "IMG", "HTMLImageElementImpl" );
+ populateElementType( "INPUT", "HTMLInputElementImpl" );
+ populateElementType( "INS", "HTMLModElementImpl" );
+ populateElementType( "ISINDEX", "HTMLIsIndexElementImpl" );
+ populateElementType( "LABEL", "HTMLLabelElementImpl" );
+ populateElementType( "LEGEND", "HTMLLegendElementImpl" );
+ populateElementType( "LI", "HTMLLIElementImpl" );
+ populateElementType( "LINK", "HTMLLinkElementImpl" );
+ populateElementType( "MAP", "HTMLMapElementImpl" );
+ populateElementType( "MENU", "HTMLMenuElementImpl" );
+ populateElementType( "META", "HTMLMetaElementImpl" );
+ populateElementType( "OBJECT", "HTMLObjectElementImpl" );
+ populateElementType( "OL", "HTMLOListElementImpl" );
+ populateElementType( "OPTGROUP", "HTMLOptGroupElementImpl" );
+ populateElementType( "OPTION", "HTMLOptionElementImpl" );
+ populateElementType( "P", "HTMLParagraphElementImpl" );
+ populateElementType( "PARAM", "HTMLParamElementImpl" );
+ populateElementType( "PRE", "HTMLPreElementImpl" );
+ populateElementType( "Q", "HTMLQuoteElementImpl" );
+ populateElementType( "SCRIPT", "HTMLScriptElementImpl" );
+ populateElementType( "SELECT", "HTMLSelectElementImpl" );
+ populateElementType( "STYLE", "HTMLStyleElementImpl" );
+ populateElementType( "TABLE", "HTMLTableElementImpl" );
+ populateElementType( "CAPTION", "HTMLTableCaptionElementImpl" );
+ populateElementType( "TD", "HTMLTableCellElementImpl" );
+ populateElementType( "TH", "HTMLTableCellElementImpl" );
+ populateElementType( "COL", "HTMLTableColElementImpl" );
+ populateElementType( "COLGROUP", "HTMLTableColElementImpl" );
+ populateElementType( "TR", "HTMLTableRowElementImpl" );
+ populateElementType( "TBODY", "HTMLTableSectionElementImpl" );
+ populateElementType( "THEAD", "HTMLTableSectionElementImpl" );
+ populateElementType( "TFOOT", "HTMLTableSectionElementImpl" );
+ populateElementType( "TEXTAREA", "HTMLTextAreaElementImpl" );
+ populateElementType( "TITLE", "HTMLTitleElementImpl" );
+ populateElementType( "UL", "HTMLUListElementImpl" );
+ }
+
+
+ private static void populateElementType( String tagName, String className )
+ {
+ try {
+ _elementTypesHTML.put( tagName,
+ ObjectFactory.findProviderClass("org.apache.html.dom." + className,
+ HTMLDocumentImpl.class.getClassLoader(), true) );
+ } catch ( Exception except ) {
+ throw new RuntimeException( "HTM019 OpenXML Error: Could not find or execute class " + className + " implementing HTML element " + tagName
+ + "\n" + className + "\t" + tagName);
+ }
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLElementImpl.java
new file mode 100644
index 0000000..e4f6a80
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLElementImpl.java
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import java.util.Locale;
+
+import org.apache.xerces.dom.ElementImpl;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.html.HTMLElement;
+import org.w3c.dom.html.HTMLFormElement;
+
+/**
+ * Implements an HTML-specific element, an {@link org.w3c.dom.Element} that
+ * will only appear inside HTML documents. This element extends {@link
+ * org.apache.xerces.dom.ElementImpl} by adding methods for directly
+ * manipulating HTML-specific attributes. All HTML elements gain access to
+ * the id , title , lang ,
+ * dir and class attributes. Other elements
+ * add their own specific attributes.
+ *
+ * @xerces.internal
+ *
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLElement
+ */
+public class HTMLElementImpl
+ extends ElementImpl
+ implements HTMLElement
+{
+
+ private static final long serialVersionUID = 5283925246324423495L;
+
+ /**
+ * Constructor required owner document and element tag name. Will be called
+ * by the constructor of specific element types but with a known tag name.
+ * Assures that the owner document is an HTML element.
+ *
+ * @param owner The owner HTML document
+ * @param tagName The element's tag name
+ */
+ public HTMLElementImpl( HTMLDocumentImpl owner, String tagName ) {
+ super( owner, tagName.toUpperCase(Locale.ENGLISH) );
+ }
+
+ public String getId() {
+ return getAttribute( "id" );
+ }
+
+ public void setId( String id ) {
+ setAttribute( "id", id );
+ }
+
+ public String getTitle() {
+ return getAttribute( "title" );
+ }
+
+ public void setTitle( String title ) {
+ setAttribute( "title", title );
+ }
+
+ public String getLang() {
+ return getAttribute( "lang" );
+ }
+
+ public void setLang( String lang ) {
+ setAttribute( "lang", lang );
+ }
+
+ public String getDir() {
+ return getAttribute( "dir" );
+ }
+
+ public void setDir( String dir ) {
+ setAttribute( "dir", dir );
+ }
+
+ public String getClassName() {
+ return getAttribute( "class" );
+ }
+
+ public void setClassName( String className ) {
+ setAttribute( "class", className );
+ }
+
+ /**
+ * Convenience method used to translate an attribute value into an integer
+ * value. Returns the integer value or zero if the attribute is not a
+ * valid numeric string.
+ *
+ * @param value The value of the attribute
+ * @return The integer value, or zero if not a valid numeric string
+ */
+ int getInteger( String value ) {
+ try {
+ return Integer.parseInt( value );
+ }
+ catch ( NumberFormatException except ) {
+ return 0;
+ }
+ }
+
+ /**
+ * Convenience method used to translate an attribute value into a boolean
+ * value. If the attribute has an associated value (even an empty string),
+ * it is set and true is returned. If the attribute does not exist, false
+ * is returend.
+ *
+ * @param value The value of the attribute
+ * @return True or false depending on whether the attribute has been set
+ */
+ boolean getBinary( String name ) {
+ return ( getAttributeNode( name ) != null );
+ }
+
+ /**
+ * Convenience method used to set a boolean attribute. If the value is true,
+ * the attribute is set to an empty string. If the value is false, the attribute
+ * is removed. HTML 4.0 understands empty strings as set attributes.
+ *
+ * @param name The name of the attribute
+ * @param value The value of the attribute
+ */
+ void setAttribute( String name, boolean value ) {
+ if ( value ) {
+ setAttribute( name, name );
+ }
+ else {
+ removeAttribute( name );
+ }
+ }
+
+ public Attr getAttributeNode( String attrName ) {
+ return super.getAttributeNode( attrName.toLowerCase(Locale.ENGLISH) );
+ }
+
+ public Attr getAttributeNodeNS( String namespaceURI,
+ String localName ) {
+ if ( namespaceURI != null && namespaceURI.length() > 0 ) {
+ return super.getAttributeNodeNS( namespaceURI, localName );
+ }
+ return super.getAttributeNode( localName.toLowerCase(Locale.ENGLISH) );
+ }
+
+ public String getAttribute( String attrName ) {
+ return super.getAttribute( attrName.toLowerCase(Locale.ENGLISH) );
+ }
+
+ public String getAttributeNS( String namespaceURI,
+ String localName ) {
+ if ( namespaceURI != null && namespaceURI.length() > 0 ) {
+ return super.getAttributeNS( namespaceURI, localName );
+ }
+ return super.getAttribute( localName.toLowerCase(Locale.ENGLISH) );
+ }
+
+ public final NodeList getElementsByTagName( String tagName ) {
+ return super.getElementsByTagName( tagName.toUpperCase(Locale.ENGLISH) );
+ }
+
+ public final NodeList getElementsByTagNameNS( String namespaceURI,
+ String localName ) {
+ if ( namespaceURI != null && namespaceURI.length() > 0 ) {
+ return super.getElementsByTagNameNS( namespaceURI, localName.toUpperCase(Locale.ENGLISH) );
+ }
+ return super.getElementsByTagName( localName.toUpperCase(Locale.ENGLISH) );
+ }
+
+ /**
+ * Convenience method used to capitalize a one-off attribute value before it
+ * is returned. For example, the align values "LEFT" and "left" will both
+ * return as "Left".
+ *
+ * @param value The value of the attribute
+ * @return The capitalized value
+ */
+ String capitalize( String value ) {
+
+ char[] chars;
+ int i;
+
+ // Convert string to charactares. Convert the first one to upper case,
+ // the other characters to lower case, and return the converted string.
+ chars = value.toCharArray();
+ if ( chars.length > 0 ) {
+ chars[ 0 ] = Character.toUpperCase( chars[ 0 ] );
+ for ( i = 1 ; i < chars.length ; ++i ) {
+ chars[ i ] = Character.toLowerCase( chars[ i ] );
+ }
+ return String.valueOf( chars );
+ }
+ return value;
+ }
+
+ /**
+ * Convenience method used to capitalize a one-off attribute value before it
+ * is returned. For example, the align values "LEFT" and "left" will both
+ * return as "Left".
+ *
+ * @param name The name of the attribute
+ * @return The capitalized value
+ */
+ String getCapitalized( String name ) {
+ String value;
+ char[] chars;
+ int i;
+
+ value = getAttribute( name );
+ if ( value != null ) {
+ // Convert string to charactares. Convert the first one to upper case,
+ // the other characters to lower case, and return the converted string.
+ chars = value.toCharArray();
+ if ( chars.length > 0 ) {
+ chars[ 0 ] = Character.toUpperCase( chars[ 0 ] );
+ for ( i = 1 ; i < chars.length ; ++i ) {
+ chars[ i ] = Character.toLowerCase( chars[ i ] );
+ }
+ return String.valueOf( chars );
+ }
+ }
+ return value;
+ }
+
+
+ /**
+ * Convenience method returns the form in which this form element is contained.
+ * This method is exposed for form elements through the DOM API, but other
+ * elements have no access to it through the API.
+ */
+ public HTMLFormElement getForm() {
+ Node parent = getParentNode();
+ while ( parent != null ) {
+ if ( parent instanceof HTMLFormElement ) {
+ return (HTMLFormElement) parent;
+ }
+ parent = parent.getParentNode();
+ }
+ return null;
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLFieldSetElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLFieldSetElementImpl.java
new file mode 100644
index 0000000..b82e1c4
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLFieldSetElementImpl.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLFieldSetElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLFieldSetElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLFieldSetElementImpl
+ extends HTMLElementImpl
+ implements HTMLFieldSetElement, HTMLFormControl
+{
+
+ private static final long serialVersionUID = 1146145578073441343L;
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLFieldSetElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLFontElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLFontElementImpl.java
new file mode 100644
index 0000000..bd1c5de
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLFontElementImpl.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLFontElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLFontElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLFontElementImpl
+ extends HTMLElementImpl
+ implements HTMLFontElement
+{
+
+ private static final long serialVersionUID = -415914342045846318L;
+
+ public String getColor()
+ {
+ return capitalize( getAttribute( "color" ) );
+ }
+
+
+ public void setColor( String color )
+ {
+ setAttribute( "color", color );
+ }
+
+
+ public String getFace()
+ {
+ return capitalize( getAttribute( "face" ) );
+ }
+
+
+ public void setFace( String face )
+ {
+ setAttribute( "face", face );
+ }
+
+
+ public String getSize()
+ {
+ return getAttribute( "size" );
+ }
+
+
+ public void setSize( String size )
+ {
+ setAttribute( "size", size );
+ }
+
+
+ public HTMLFontElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLFormControl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLFormControl.java
new file mode 100644
index 0000000..1135cbc
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLFormControl.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+
+/**
+ * Identifies control in a form, so they may be collected in a form elements
+ * collection. All form control elements implement this empty interface.
+ *
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ */
+public interface HTMLFormControl
+{
+}
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLFormElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLFormElementImpl.java
new file mode 100644
index 0000000..b297386
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLFormElementImpl.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.html.HTMLCollection;
+import org.w3c.dom.html.HTMLFormElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLFormElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLFormElementImpl
+ extends HTMLElementImpl
+ implements HTMLFormElement
+{
+
+ private static final long serialVersionUID = -7324749629151493210L;
+
+ public HTMLCollection getElements()
+ {
+ if ( _elements == null )
+ _elements = new HTMLCollectionImpl( this, HTMLCollectionImpl.ELEMENT );
+ return _elements;
+ }
+
+
+ public int getLength()
+ {
+ return getElements().getLength();
+ }
+
+
+ public String getName()
+ {
+ return getAttribute( "name" );
+ }
+
+
+ public void setName( String name )
+ {
+ setAttribute( "name", name );
+ }
+
+
+ public String getAcceptCharset()
+ {
+ return getAttribute( "accept-charset" );
+ }
+
+
+ public void setAcceptCharset( String acceptCharset )
+ {
+ setAttribute( "accept-charset", acceptCharset );
+ }
+
+
+ public String getAction()
+ {
+ return getAttribute( "action" );
+ }
+
+
+ public void setAction( String action )
+ {
+ setAttribute( "action", action );
+ }
+
+
+ public String getEnctype()
+ {
+ return getAttribute( "enctype" );
+ }
+
+
+ public void setEnctype( String enctype )
+ {
+ setAttribute( "enctype", enctype );
+ }
+
+
+ public String getMethod()
+ {
+ return capitalize( getAttribute( "method" ) );
+ }
+
+
+ public void setMethod( String method )
+ {
+ setAttribute( "method", method );
+ }
+
+
+ public String getTarget()
+ {
+ return getAttribute( "target" );
+ }
+
+
+ public void setTarget( String target )
+ {
+ setAttribute( "target", target );
+ }
+
+
+ public void submit()
+ {
+ // No scripting in server-side DOM. This method is moot.
+ }
+
+
+ public void reset()
+ {
+ // No scripting in server-side DOM. This method is moot.
+ }
+
+ /*
+ * Explicit implementation of getChildNodes() to avoid problems with
+ * overriding the getLength() method hidden in the super class.
+ */
+ public NodeList getChildNodes() {
+ return getChildNodesUnoptimized();
+ }
+
+ /**
+ * Explicit implementation of cloneNode() to ensure that cache used
+ * for getElements() gets cleared.
+ */
+ public Node cloneNode( boolean deep ) {
+ HTMLFormElementImpl clonedNode = (HTMLFormElementImpl)super.cloneNode( deep );
+ clonedNode._elements = null;
+ return clonedNode;
+ }
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLFormElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+ /**
+ * Collection of all elements contained in this FORM.
+ */
+ private HTMLCollectionImpl _elements;
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLFrameElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLFrameElementImpl.java
new file mode 100644
index 0000000..913c6ba
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLFrameElementImpl.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLFrameElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLFrameElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLFrameElementImpl
+ extends HTMLElementImpl
+ implements HTMLFrameElement
+{
+
+ private static final long serialVersionUID = 635237057173695984L;
+
+ public String getFrameBorder()
+ {
+ return getAttribute( "frameborder" );
+ }
+
+
+ public void setFrameBorder( String frameBorder )
+ {
+ setAttribute( "frameborder", frameBorder );
+ }
+
+
+ public String getLongDesc()
+ {
+ return getAttribute( "longdesc" );
+ }
+
+
+ public void setLongDesc( String longDesc )
+ {
+ setAttribute( "longdesc", longDesc );
+ }
+
+
+ public String getMarginHeight()
+ {
+ return getAttribute( "marginheight" );
+ }
+
+
+ public void setMarginHeight( String marginHeight )
+ {
+ setAttribute( "marginheight", marginHeight );
+ }
+
+
+ public String getMarginWidth()
+ {
+ return getAttribute( "marginwidth" );
+ }
+
+
+ public void setMarginWidth( String marginWidth )
+ {
+ setAttribute( "marginwidth", marginWidth );
+ }
+
+
+ public String getName()
+ {
+ return getAttribute( "name" );
+ }
+
+
+ public void setName( String name )
+ {
+ setAttribute( "name", name );
+ }
+
+
+ public boolean getNoResize()
+ {
+ return getBinary( "noresize" );
+ }
+
+
+ public void setNoResize( boolean noResize )
+ {
+ setAttribute( "noresize", noResize );
+ }
+
+
+ public String getScrolling()
+ {
+ return capitalize( getAttribute( "scrolling" ) );
+ }
+
+
+ public void setScrolling( String scrolling )
+ {
+ setAttribute( "scrolling", scrolling );
+ }
+
+
+ public String getSrc()
+ {
+ return getAttribute( "src" );
+ }
+
+
+ public void setSrc( String src )
+ {
+ setAttribute( "src", src );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLFrameElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLFrameSetElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLFrameSetElementImpl.java
new file mode 100644
index 0000000..1670130
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLFrameSetElementImpl.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLFrameSetElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLFrameSetElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLFrameSetElementImpl
+ extends HTMLElementImpl
+ implements HTMLFrameSetElement
+{
+
+ private static final long serialVersionUID = 8403143821972586708L;
+
+ public String getCols()
+ {
+ return getAttribute( "cols" );
+ }
+
+
+ public void setCols( String cols )
+ {
+ setAttribute( "cols", cols );
+ }
+
+
+ public String getRows()
+ {
+ return getAttribute( "rows" );
+ }
+
+
+ public void setRows( String rows )
+ {
+ setAttribute( "rows", rows );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLFrameSetElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLHRElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLHRElementImpl.java
new file mode 100644
index 0000000..6d29c10
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLHRElementImpl.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLHRElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLHRElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLHRElementImpl
+ extends HTMLElementImpl
+ implements HTMLHRElement
+{
+
+ private static final long serialVersionUID = -4210053417678939270L;
+
+ public String getAlign()
+ {
+ return capitalize( getAttribute( "align" ) );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ public boolean getNoShade()
+ {
+ return getBinary( "noshade" );
+ }
+
+
+ public void setNoShade( boolean noShade )
+ {
+ setAttribute( "noshade", noShade );
+ }
+
+
+ public String getSize()
+ {
+ return getAttribute( "size" );
+ }
+
+
+ public void setSize( String size )
+ {
+ setAttribute( "size", size );
+ }
+
+
+ public String getWidth()
+ {
+ return getAttribute( "width" );
+ }
+
+
+ public void setWidth( String width )
+ {
+ setAttribute( "width", width );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLHRElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLHeadElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLHeadElementImpl.java
new file mode 100644
index 0000000..8bda2cd
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLHeadElementImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLHeadElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLHeadElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLHeadElementImpl
+ extends HTMLElementImpl
+ implements HTMLHeadElement
+{
+
+ private static final long serialVersionUID = 6438668473721292232L;
+
+ public String getProfile()
+ {
+ return getAttribute( "profile" );
+ }
+
+
+ public void setProfile( String profile )
+ {
+ setAttribute( "profile", profile );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLHeadElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLHeadingElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLHeadingElementImpl.java
new file mode 100644
index 0000000..b977ab2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLHeadingElementImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLHeadingElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLHeadingElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLHeadingElementImpl
+ extends HTMLElementImpl
+ implements HTMLHeadingElement
+{
+
+ private static final long serialVersionUID = 6605827989383069095L;
+
+ public String getAlign()
+ {
+ return getCapitalized( "align" );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLHeadingElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLHtmlElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLHtmlElementImpl.java
new file mode 100644
index 0000000..bc640e9
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLHtmlElementImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLHtmlElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLHtmlElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLHtmlElementImpl
+ extends HTMLElementImpl
+ implements HTMLHtmlElement
+{
+
+ private static final long serialVersionUID = -4489734201536616166L;
+
+ public String getVersion()
+ {
+ return capitalize( getAttribute( "version" ) );
+ }
+
+
+ public void setVersion( String version )
+ {
+ setAttribute( "version", version );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLHtmlElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLIFrameElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLIFrameElementImpl.java
new file mode 100644
index 0000000..ab01942
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLIFrameElementImpl.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLIFrameElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLIFrameElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLIFrameElementImpl
+ extends HTMLElementImpl
+ implements HTMLIFrameElement
+{
+
+ private static final long serialVersionUID = 2393622754706230429L;
+
+ public String getAlign()
+ {
+ return capitalize( getAttribute( "align" ) );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ public String getFrameBorder()
+ {
+ return getAttribute( "frameborder" );
+ }
+
+
+ public void setFrameBorder( String frameBorder )
+ {
+ setAttribute( "frameborder", frameBorder );
+ }
+
+
+ public String getHeight()
+ {
+ return getAttribute( "height" );
+ }
+
+
+ public void setHeight( String height )
+ {
+ setAttribute( "height", height );
+ }
+
+ public String getLongDesc()
+ {
+ return getAttribute( "longdesc" );
+ }
+
+
+ public void setLongDesc( String longDesc )
+ {
+ setAttribute( "longdesc", longDesc );
+ }
+
+
+ public String getMarginHeight()
+ {
+ return getAttribute( "marginheight" );
+ }
+
+
+ public void setMarginHeight( String marginHeight )
+ {
+ setAttribute( "marginheight", marginHeight );
+ }
+
+
+ public String getMarginWidth()
+ {
+ return getAttribute( "marginwidth" );
+ }
+
+
+ public void setMarginWidth( String marginWidth )
+ {
+ setAttribute( "marginwidth", marginWidth );
+ }
+
+
+ public String getName()
+ {
+ return getAttribute( "name" );
+ }
+
+
+ public void setName( String name )
+ {
+ setAttribute( "name", name );
+ }
+
+
+ public String getScrolling()
+ {
+ return capitalize( getAttribute( "scrolling" ) );
+ }
+
+
+ public void setScrolling( String scrolling )
+ {
+ setAttribute( "scrolling", scrolling );
+ }
+
+
+ public String getSrc()
+ {
+ return getAttribute( "src" );
+ }
+
+
+ public void setSrc( String src )
+ {
+ setAttribute( "src", src );
+ }
+
+
+ public String getWidth()
+ {
+ return getAttribute( "width" );
+ }
+
+
+ public void setWidth( String width )
+ {
+ setAttribute( "width", width );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLIFrameElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLImageElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLImageElementImpl.java
new file mode 100644
index 0000000..8862482
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLImageElementImpl.java
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLImageElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLImageElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLImageElementImpl
+ extends HTMLElementImpl
+ implements HTMLImageElement
+{
+
+ private static final long serialVersionUID = 1424360710977241315L;
+
+ public String getLowSrc()
+ {
+ return getAttribute( "lowsrc" );
+ }
+
+
+ public void setLowSrc( String lowSrc )
+ {
+ setAttribute( "lowsrc", lowSrc );
+ }
+
+
+ public String getSrc()
+ {
+ return getAttribute( "src" );
+ }
+
+
+ public void setSrc( String src )
+ {
+ setAttribute( "src", src );
+ }
+
+
+ public String getName()
+ {
+ return getAttribute( "name" );
+ }
+
+
+ public void setName( String name )
+ {
+ setAttribute( "name", name );
+ }
+
+
+ public String getAlign()
+ {
+ return capitalize( getAttribute( "align" ) );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ public String getAlt()
+ {
+ return getAttribute( "alt" );
+ }
+
+
+ public void setAlt( String alt )
+ {
+ setAttribute( "alt", alt );
+ }
+
+
+ public String getBorder()
+ {
+ return getAttribute( "border" );
+ }
+
+
+ public void setBorder( String border )
+ {
+ setAttribute( "border", border );
+ }
+
+
+ public String getHeight()
+ {
+ return getAttribute( "height" );
+ }
+
+
+ public void setHeight( String height )
+ {
+ setAttribute( "height", height );
+ }
+
+
+ public String getHspace()
+ {
+ return getAttribute( "hspace" );
+ }
+
+
+ public void setHspace( String hspace )
+ {
+ setAttribute( "hspace", hspace );
+ }
+
+
+ public boolean getIsMap()
+ {
+ return getBinary( "ismap" );
+ }
+
+
+ public void setIsMap( boolean isMap )
+ {
+ setAttribute( "ismap", isMap );
+ }
+
+
+ public String getLongDesc()
+ {
+ return getAttribute( "longdesc" );
+ }
+
+
+ public void setLongDesc( String longDesc )
+ {
+ setAttribute( "longdesc", longDesc );
+ }
+
+
+ public String getUseMap()
+ {
+ return getAttribute( "useMap" );
+ }
+
+
+ public void setUseMap( String useMap )
+ {
+ setAttribute( "useMap", useMap );
+ }
+
+
+ public String getVspace()
+ {
+ return getAttribute( "vspace" );
+ }
+
+
+ public void setVspace( String vspace )
+ {
+ setAttribute( "vspace", vspace );
+ }
+
+
+ public String getWidth()
+ {
+ return getAttribute( "width" );
+ }
+
+
+ public void setWidth( String width )
+ {
+ setAttribute( "width", width );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLImageElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLInputElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLInputElementImpl.java
new file mode 100644
index 0000000..1a1fcd2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLInputElementImpl.java
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLInputElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLInputElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLInputElementImpl
+ extends HTMLElementImpl
+ implements HTMLInputElement, HTMLFormControl
+{
+
+ private static final long serialVersionUID = 640139325394332007L;
+
+ public String getDefaultValue()
+ {
+ // ! NOT FULLY IMPLEMENTED !
+ return getAttribute( "defaultValue" );
+ }
+
+
+ public void setDefaultValue( String defaultValue )
+ {
+ // ! NOT FULLY IMPLEMENTED !
+ setAttribute( "defaultValue", defaultValue );
+ }
+
+
+ public boolean getDefaultChecked()
+ {
+ // ! NOT FULLY IMPLEMENTED !
+ return getBinary( "defaultChecked" );
+ }
+
+
+ public void setDefaultChecked( boolean defaultChecked )
+ {
+ // ! NOT FULLY IMPLEMENTED !
+ setAttribute( "defaultChecked", defaultChecked );
+ }
+
+
+ public String getAccept()
+ {
+ return getAttribute( "accept" );
+ }
+
+
+ public void setAccept( String accept )
+ {
+ setAttribute( "accept", accept );
+ }
+
+
+ public String getAccessKey()
+ {
+ String accessKey;
+
+ // Make sure that the access key is a single character.
+ accessKey = getAttribute( "accesskey" );
+ if ( accessKey != null && accessKey.length() > 1 )
+ accessKey = accessKey.substring( 0, 1 );
+ return accessKey;
+ }
+
+
+ public void setAccessKey( String accessKey )
+ {
+ // Make sure that the access key is a single character.
+ if ( accessKey != null && accessKey.length() > 1 )
+ accessKey = accessKey.substring( 0, 1 );
+ setAttribute( "accesskey", accessKey );
+ }
+
+
+ public String getAlign()
+ {
+ return capitalize( getAttribute( "align" ) );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ public String getAlt()
+ {
+ return getAttribute( "alt" );
+ }
+
+
+ public void setAlt( String alt )
+ {
+ setAttribute( "alt", alt );
+ }
+
+
+ public boolean getChecked()
+ {
+ return getBinary( "checked" );
+ }
+
+
+ public void setChecked( boolean checked )
+ {
+ setAttribute( "checked", checked );
+ }
+
+
+ public boolean getDisabled()
+ {
+ return getBinary( "disabled" );
+ }
+
+
+ public void setDisabled( boolean disabled )
+ {
+ setAttribute( "disabled", disabled );
+ }
+
+
+ public int getMaxLength()
+ {
+ return getInteger( getAttribute( "maxlength" ) );
+ }
+
+
+ public void setMaxLength( int maxLength )
+ {
+ setAttribute( "maxlength", String.valueOf( maxLength ) );
+ }
+
+
+ public String getName()
+ {
+ return getAttribute( "name" );
+ }
+
+
+ public void setName( String name )
+ {
+ setAttribute( "name", name );
+ }
+
+
+ public boolean getReadOnly()
+ {
+ return getBinary( "readonly" );
+ }
+
+
+ public void setReadOnly( boolean readOnly )
+ {
+ setAttribute( "readonly", readOnly );
+ }
+
+
+ public String getSize()
+ {
+ return getAttribute( "size" );
+ }
+
+
+ public void setSize( String size )
+ {
+ setAttribute( "size", size );
+ }
+
+
+ public String getSrc()
+ {
+ return getAttribute( "src" );
+ }
+
+
+ public void setSrc( String src )
+ {
+ setAttribute( "src", src );
+ }
+
+
+ public int getTabIndex()
+ {
+ try
+ {
+ return Integer.parseInt( getAttribute( "tabindex" ) );
+ }
+ catch ( NumberFormatException except )
+ {
+ return 0;
+ }
+ }
+
+
+ public void setTabIndex( int tabIndex )
+ {
+ setAttribute( "tabindex", String.valueOf( tabIndex ) );
+ }
+
+
+ public String getType()
+ {
+ return getAttribute( "type" );
+ }
+
+
+ public String getUseMap()
+ {
+ return getAttribute( "useMap" );
+ }
+
+
+ public void setUseMap( String useMap )
+ {
+ setAttribute( "useMap", useMap );
+ }
+
+
+ public String getValue()
+ {
+ return getAttribute( "value" );
+ }
+
+
+ public void setValue( String value )
+ {
+ setAttribute( "value", value );
+ }
+
+
+ public void blur()
+ {
+ // No scripting in server-side DOM. This method is moot.
+ }
+
+
+ public void focus()
+ {
+ // No scripting in server-side DOM. This method is moot.
+ }
+
+
+ public void select()
+ {
+ // No scripting in server-side DOM. This method is moot.
+ }
+
+
+ public void click()
+ {
+ // No scripting in server-side DOM. This method is moot.
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLInputElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLIsIndexElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLIsIndexElementImpl.java
new file mode 100644
index 0000000..0cdd50b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLIsIndexElementImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLIsIndexElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLIsIndexElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLIsIndexElementImpl
+ extends HTMLElementImpl
+ implements HTMLIsIndexElement
+{
+
+ private static final long serialVersionUID = 3073521742049689699L;
+
+ public String getPrompt()
+ {
+ return getAttribute( "prompt" );
+ }
+
+
+ public void setPrompt( String prompt )
+ {
+ setAttribute( "prompt", prompt );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLIsIndexElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLLIElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLLIElementImpl.java
new file mode 100644
index 0000000..a523d5e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLLIElementImpl.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLLIElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLLIElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLLIElementImpl
+ extends HTMLElementImpl
+ implements HTMLLIElement
+{
+
+ private static final long serialVersionUID = -8987309345926701831L;
+
+ public String getType()
+ {
+ return getAttribute( "type" );
+ }
+
+
+ public void setType( String type )
+ {
+ setAttribute( "type", type );
+ }
+
+
+ public int getValue()
+ {
+ return getInteger( getAttribute( "value" ) );
+ }
+
+
+ public void setValue( int value )
+ {
+ setAttribute( "value", String.valueOf( value ) );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLLIElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLLabelElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLLabelElementImpl.java
new file mode 100644
index 0000000..6888607
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLLabelElementImpl.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLLabelElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLLabelElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLLabelElementImpl
+ extends HTMLElementImpl
+ implements HTMLLabelElement, HTMLFormControl
+{
+
+ private static final long serialVersionUID = 5774388295313199380L;
+
+ public String getAccessKey()
+ {
+ String accessKey;
+
+ // Make sure that the access key is a single character.
+ accessKey = getAttribute( "accesskey" );
+ if ( accessKey != null && accessKey.length() > 1 )
+ accessKey = accessKey.substring( 0, 1 );
+ return accessKey;
+ }
+
+
+ public void setAccessKey( String accessKey )
+ {
+ // Make sure that the access key is a single character.
+ if ( accessKey != null && accessKey.length() > 1 )
+ accessKey = accessKey.substring( 0, 1 );
+ setAttribute( "accesskey", accessKey );
+ }
+
+
+ public String getHtmlFor()
+ {
+ return getAttribute( "for" );
+ }
+
+
+ public void setHtmlFor( String htmlFor )
+ {
+ setAttribute( "for", htmlFor );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLLabelElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLLegendElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLLegendElementImpl.java
new file mode 100644
index 0000000..730df73
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLLegendElementImpl.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLLegendElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLLegendElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLLegendElementImpl
+ extends HTMLElementImpl
+ implements HTMLLegendElement
+{
+
+ private static final long serialVersionUID = -621849164029630762L;
+
+ public String getAccessKey()
+ {
+ String accessKey;
+
+ // Make sure that the access key is a single character.
+ accessKey = getAttribute( "accesskey" );
+ if ( accessKey != null && accessKey.length() > 1 )
+ accessKey = accessKey.substring( 0, 1 );
+ return accessKey;
+ }
+
+
+ public void setAccessKey( String accessKey )
+ {
+ // Make sure that the access key is a single character.
+ if ( accessKey != null && accessKey.length() > 1 )
+ accessKey = accessKey.substring( 0, 1 );
+ setAttribute( "accesskey", accessKey );
+ }
+
+
+ public String getAlign()
+ {
+ return getAttribute( "align" );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLLegendElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLLinkElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLLinkElementImpl.java
new file mode 100644
index 0000000..e2f2449
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLLinkElementImpl.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLLinkElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLLinkElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLLinkElementImpl
+ extends HTMLElementImpl
+ implements HTMLLinkElement
+{
+
+ private static final long serialVersionUID = 874345520063418879L;
+
+ public boolean getDisabled()
+ {
+ return getBinary( "disabled" );
+ }
+
+
+ public void setDisabled( boolean disabled )
+ {
+ setAttribute( "disabled", disabled );
+ }
+
+
+ public String getCharset()
+ {
+ return getAttribute( "charset" );
+ }
+
+
+ public void setCharset( String charset )
+ {
+ setAttribute( "charset", charset );
+ }
+
+
+ public String getHref()
+ {
+ return getAttribute( "href" );
+ }
+
+
+ public void setHref( String href )
+ {
+ setAttribute( "href", href );
+ }
+
+
+ public String getHreflang()
+ {
+ return getAttribute( "hreflang" );
+ }
+
+
+ public void setHreflang( String hreflang )
+ {
+ setAttribute( "hreflang", hreflang );
+ }
+
+
+ public String getMedia()
+ {
+ return getAttribute( "media" );
+ }
+
+
+ public void setMedia( String media )
+ {
+ setAttribute( "media", media );
+ }
+
+
+ public String getRel()
+ {
+ return getAttribute( "rel" );
+ }
+
+
+ public void setRel( String rel )
+ {
+ setAttribute( "rel", rel );
+ }
+
+
+ public String getRev()
+ {
+ return getAttribute( "rev" );
+ }
+
+
+ public void setRev( String rev )
+ {
+ setAttribute( "rev", rev );
+ }
+
+
+ public String getTarget()
+ {
+ return getAttribute( "target" );
+ }
+
+
+ public void setTarget( String target )
+ {
+ setAttribute( "target", target );
+ }
+
+
+ public String getType()
+ {
+ return getAttribute( "type" );
+ }
+
+
+ public void setType( String type )
+ {
+ setAttribute( "type", type );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLLinkElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLMapElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLMapElementImpl.java
new file mode 100644
index 0000000..a25cead
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLMapElementImpl.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.html.HTMLCollection;
+import org.w3c.dom.html.HTMLMapElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLMapElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLMapElementImpl
+ extends HTMLElementImpl
+ implements HTMLMapElement
+{
+
+ private static final long serialVersionUID = 7520887584251976392L;
+
+ public HTMLCollection getAreas()
+ {
+ if ( _areas == null )
+ _areas = new HTMLCollectionImpl( this, HTMLCollectionImpl.AREA );
+ return _areas;
+ }
+
+
+ public String getName()
+ {
+ return getAttribute( "name" );
+ }
+
+
+ public void setName( String name )
+ {
+ setAttribute( "name", name );
+ }
+
+ /**
+ * Explicit implementation of cloneNode() to ensure that cache used
+ * for getAreas() gets cleared.
+ */
+ public Node cloneNode( boolean deep )
+ {
+ HTMLMapElementImpl clonedNode = (HTMLMapElementImpl)super.cloneNode( deep );
+ clonedNode._areas = null;
+ return clonedNode;
+ }
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLMapElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+ private HTMLCollection _areas;
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLMenuElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLMenuElementImpl.java
new file mode 100644
index 0000000..5010064
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLMenuElementImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLMenuElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLMenuElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLMenuElementImpl
+ extends HTMLElementImpl
+ implements HTMLMenuElement
+{
+
+ private static final long serialVersionUID = -1489696654903916901L;
+
+ public boolean getCompact()
+ {
+ return getBinary( "compact" );
+ }
+
+
+ public void setCompact( boolean compact )
+ {
+ setAttribute( "compact", compact );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLMenuElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLMetaElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLMetaElementImpl.java
new file mode 100644
index 0000000..47c2e62
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLMetaElementImpl.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLMetaElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLMetaElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLMetaElementImpl
+ extends HTMLElementImpl
+ implements HTMLMetaElement
+{
+
+ private static final long serialVersionUID = -2401961905874264272L;
+
+ public String getContent()
+ {
+ return getAttribute( "content" );
+ }
+
+
+ public void setContent( String content )
+ {
+ setAttribute( "content", content );
+ }
+
+
+
+ public String getHttpEquiv()
+ {
+ return getAttribute( "http-equiv" );
+ }
+
+
+ public void setHttpEquiv( String httpEquiv )
+ {
+ setAttribute( "http-equiv", httpEquiv );
+ }
+
+
+ public String getName()
+ {
+ return getAttribute( "name" );
+ }
+
+
+ public void setName( String name )
+ {
+ setAttribute( "name", name );
+ }
+
+
+ public String getScheme()
+ {
+ return getAttribute( "scheme" );
+ }
+
+
+ public void setScheme( String scheme )
+ {
+ setAttribute( "scheme", scheme );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLMetaElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLModElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLModElementImpl.java
new file mode 100644
index 0000000..cf1211d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLModElementImpl.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLModElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLModElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLModElementImpl
+ extends HTMLElementImpl
+ implements HTMLModElement
+{
+
+ private static final long serialVersionUID = 6424581972706750120L;
+
+ public String getCite()
+ {
+ return getAttribute( "cite" );
+ }
+
+
+ public void setCite( String cite )
+ {
+ setAttribute( "cite", cite );
+ }
+
+
+ public String getDateTime()
+ {
+ return getAttribute( "datetime" );
+ }
+
+
+ public void setDateTime( String dateTime )
+ {
+ setAttribute( "datetime", dateTime );
+ }
+
+
+ /**
+ * Constructor requires owner document and tag name.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLModElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLOListElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLOListElementImpl.java
new file mode 100644
index 0000000..5941956
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLOListElementImpl.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLOListElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLOListElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLOListElementImpl
+ extends HTMLElementImpl
+ implements HTMLOListElement
+{
+
+ private static final long serialVersionUID = 1293750546025862146L;
+
+ public boolean getCompact()
+ {
+ return getBinary( "compact" );
+ }
+
+
+ public void setCompact( boolean compact )
+ {
+ setAttribute( "compact", compact );
+ }
+
+
+ public int getStart()
+ {
+ return getInteger( getAttribute( "start" ) );
+ }
+
+
+ public void setStart( int start )
+ {
+ setAttribute( "start", String.valueOf( start ) );
+ }
+
+
+ public String getType()
+ {
+ return getAttribute( "type" );
+ }
+
+
+ public void setType( String type )
+ {
+ setAttribute( "type", type );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLOListElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLObjectElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLObjectElementImpl.java
new file mode 100644
index 0000000..cc31952
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLObjectElementImpl.java
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLObjectElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLObjectElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLObjectElementImpl
+ extends HTMLElementImpl
+ implements HTMLObjectElement, HTMLFormControl
+{
+
+ private static final long serialVersionUID = 2276953229932965067L;
+
+ public String getCode()
+ {
+ return getAttribute( "code" );
+ }
+
+
+ public void setCode( String code )
+ {
+ setAttribute( "code", code );
+ }
+
+
+ public String getAlign()
+ {
+ return capitalize( getAttribute( "align" ) );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ public String getArchive()
+ {
+ return getAttribute( "archive" );
+ }
+
+
+ public void setArchive( String archive )
+ {
+ setAttribute( "archive", archive );
+ }
+
+ public String getBorder()
+ {
+ return getAttribute( "border" );
+ }
+
+
+ public void setBorder( String border )
+ {
+ setAttribute( "border", border );
+ }
+
+
+ public String getCodeBase()
+ {
+ return getAttribute( "codebase" );
+ }
+
+
+ public void setCodeBase( String codeBase )
+ {
+ setAttribute( "codebase", codeBase );
+ }
+
+
+ public String getCodeType()
+ {
+ return getAttribute( "codetype" );
+ }
+
+
+ public void setCodeType( String codeType )
+ {
+ setAttribute( "codetype", codeType );
+ }
+
+
+ public String getData()
+ {
+ return getAttribute( "data" );
+ }
+
+
+ public void setData( String data )
+ {
+ setAttribute( "data", data );
+ }
+
+
+ public boolean getDeclare()
+ {
+ return getBinary( "declare" );
+ }
+
+
+ public void setDeclare( boolean declare )
+ {
+ setAttribute( "declare", declare );
+ }
+
+
+ public String getHeight()
+ {
+ return getAttribute( "height" );
+ }
+
+
+ public void setHeight( String height )
+ {
+ setAttribute( "height", height );
+ }
+
+
+ public String getHspace()
+ {
+ return getAttribute( "hspace" );
+ }
+
+
+ public void setHspace( String hspace )
+ {
+ setAttribute( "hspace", hspace );
+ }
+
+ public String getName()
+ {
+ return getAttribute( "name" );
+ }
+
+
+ public void setName( String name )
+ {
+ setAttribute( "name", name );
+ }
+
+
+ public String getStandby()
+ {
+ return getAttribute( "standby" );
+ }
+
+
+ public void setStandby( String standby )
+ {
+ setAttribute( "standby", standby );
+ }
+
+ public int getTabIndex()
+ {
+ try
+ {
+ return Integer.parseInt( getAttribute( "tabindex" ) );
+ }
+ catch ( NumberFormatException except )
+ {
+ return 0;
+ }
+ }
+
+
+ public void setTabIndex( int tabIndex )
+ {
+ setAttribute( "tabindex", String.valueOf( tabIndex ) );
+ }
+
+
+ public String getType()
+ {
+ return getAttribute( "type" );
+ }
+
+
+ public void setType( String type )
+ {
+ setAttribute( "type", type );
+ }
+
+
+ public String getUseMap()
+ {
+ return getAttribute( "useMap" );
+ }
+
+
+ public void setUseMap( String useMap )
+ {
+ setAttribute( "useMap", useMap );
+ }
+
+
+ public String getVspace()
+ {
+ return getAttribute( "vspace" );
+ }
+
+
+ public void setVspace( String vspace )
+ {
+ setAttribute( "vspace", vspace );
+ }
+
+
+ public String getWidth()
+ {
+ return getAttribute( "width" );
+ }
+
+
+ public void setWidth( String width )
+ {
+ setAttribute( "width", width );
+ }
+
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLObjectElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLOptGroupElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLOptGroupElementImpl.java
new file mode 100644
index 0000000..0463c67
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLOptGroupElementImpl.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLOptGroupElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLOptGroupElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLOptGroupElementImpl
+ extends HTMLElementImpl
+ implements HTMLOptGroupElement
+{
+
+ private static final long serialVersionUID = -8807098641226171501L;
+
+ public boolean getDisabled()
+ {
+ return getBinary( "disabled" );
+ }
+
+
+ public void setDisabled( boolean disabled )
+ {
+ setAttribute( "disabled", disabled );
+ }
+
+
+ public String getLabel()
+ {
+ return capitalize( getAttribute( "label" ) );
+ }
+
+
+ public void setLabel( String label )
+ {
+ setAttribute( "label", label );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLOptGroupElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLOptionElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLOptionElementImpl.java
new file mode 100644
index 0000000..75ce3b2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLOptionElementImpl.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.w3c.dom.html.HTMLElement;
+import org.w3c.dom.html.HTMLOptionElement;
+import org.w3c.dom.html.HTMLSelectElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLOptionElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLOptionElementImpl
+ extends HTMLElementImpl
+ implements HTMLOptionElement
+{
+
+ private static final long serialVersionUID = -4486774554137530907L;
+
+ public boolean getDefaultSelected()
+ {
+ // ! NOT FULLY IMPLEMENTED !
+ return getBinary( "default-selected" );
+ }
+
+
+ public void setDefaultSelected( boolean defaultSelected )
+ {
+ // ! NOT FULLY IMPLEMENTED !
+ setAttribute( "default-selected", defaultSelected );
+ }
+
+
+ public String getText()
+ {
+ Node child;
+ StringBuffer text = new StringBuffer();
+
+ // Find the Text nodes contained within this element and return their
+ // concatenated value. Required to go around comments, entities, etc.
+ child = getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof Text ) {
+ text.append(( (Text) child ).getData());
+ }
+ child = child.getNextSibling();
+ }
+ return text.toString();
+ }
+
+
+ public void setText( String text )
+ {
+ Node child;
+ Node next;
+
+ // Delete all the nodes and replace them with a single Text node.
+ // This is the only approach that can handle comments and other nodes.
+ child = getFirstChild();
+ while ( child != null )
+ {
+ next = child.getNextSibling();
+ removeChild( child );
+ child = next;
+ }
+ insertBefore( getOwnerDocument().createTextNode( text ), getFirstChild() );
+ }
+
+
+ public int getIndex()
+ {
+ Node parent;
+ NodeList options;
+ int i;
+
+ // Locate the parent SELECT. Note that this OPTION might be inside a
+ // OPTGROUP inside the SELECT. Or it might not have a parent SELECT.
+ // Everything is possible. If no parent is found, return -1.
+ parent = getParentNode();
+ while ( parent != null && ! ( parent instanceof HTMLSelectElement ) )
+ parent = parent.getParentNode();
+ if ( parent != null )
+ {
+ // Use getElementsByTagName() which creates a snapshot of all the
+ // OPTION elements under the SELECT. Access to the returned NodeList
+ // is very fast and the snapshot solves many synchronization problems.
+ options = ( (HTMLElement) parent ).getElementsByTagName( "OPTION" );
+ for ( i = 0 ; i < options.getLength() ; ++i )
+ if ( options.item( i ) == this )
+ return i;
+ }
+ return -1;
+ }
+
+
+ public void setIndex( int index )
+ {
+ Node parent;
+ NodeList options;
+ Node item;
+
+ // Locate the parent SELECT. Note that this OPTION might be inside a
+ // OPTGROUP inside the SELECT. Or it might not have a parent SELECT.
+ // Everything is possible. If no parent is found, just return.
+ parent = getParentNode();
+ while ( parent != null && ! ( parent instanceof HTMLSelectElement ) )
+ parent = parent.getParentNode();
+ if ( parent != null )
+ {
+ // Use getElementsByTagName() which creates a snapshot of all the
+ // OPTION elements under the SELECT. Access to the returned NodeList
+ // is very fast and the snapshot solves many synchronization problems.
+ // Make sure this OPTION is not replacing itself.
+ options = ( (HTMLElement) parent ).getElementsByTagName( "OPTION" );
+ if ( options.item( index ) != this )
+ {
+ // Remove this OPTION from its parent. Place this OPTION right
+ // before indexed OPTION underneath it's direct parent (might
+ // be an OPTGROUP).
+ getParentNode().removeChild( this );
+ item = options.item( index );
+ item.getParentNode().insertBefore( this, item );
+ }
+ }
+ }
+
+
+ public boolean getDisabled()
+ {
+ return getBinary( "disabled" );
+ }
+
+
+ public void setDisabled( boolean disabled )
+ {
+ setAttribute( "disabled", disabled );
+ }
+
+
+ public String getLabel()
+ {
+ return capitalize( getAttribute( "label" ) );
+ }
+
+
+ public void setLabel( String label )
+ {
+ setAttribute( "label", label );
+ }
+
+
+ public boolean getSelected()
+ {
+ return getBinary( "selected" );
+ }
+
+
+ public void setSelected( boolean selected )
+ {
+ setAttribute( "selected", selected );
+ }
+
+
+ public String getValue()
+ {
+ return getAttribute( "value" );
+ }
+
+
+ public void setValue( String value )
+ {
+ setAttribute( "value", value );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLOptionElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLParagraphElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLParagraphElementImpl.java
new file mode 100644
index 0000000..c3e21f5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLParagraphElementImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLParagraphElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLParagraphElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLParagraphElementImpl
+ extends HTMLElementImpl
+ implements HTMLParagraphElement
+{
+
+ private static final long serialVersionUID = 8075287150683866287L;
+
+ public String getAlign()
+ {
+ return getAttribute( "align" );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLParagraphElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLParamElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLParamElementImpl.java
new file mode 100644
index 0000000..03cf192
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLParamElementImpl.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLParamElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLParamElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLParamElementImpl
+ extends HTMLElementImpl
+ implements HTMLParamElement
+{
+
+ private static final long serialVersionUID = -8513050483880341412L;
+
+ public String getName()
+ {
+ return getAttribute( "name" );
+ }
+
+
+ public void setName( String name )
+ {
+ setAttribute( "name", name );
+ }
+
+
+ public String getType()
+ {
+ return getAttribute( "type" );
+ }
+
+
+ public void setType( String type )
+ {
+ setAttribute( "type", type );
+ }
+
+
+ public String getValue()
+ {
+ return getAttribute( "value" );
+ }
+
+
+ public void setValue( String value )
+ {
+ setAttribute( "value", value );
+ }
+
+
+ public String getValueType()
+ {
+ return capitalize( getAttribute( "valuetype" ) );
+ }
+
+
+ public void setValueType( String valueType )
+ {
+ setAttribute( "valuetype", valueType );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLParamElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLPreElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLPreElementImpl.java
new file mode 100644
index 0000000..63f4f6e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLPreElementImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLPreElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLPreElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLPreElementImpl
+ extends HTMLElementImpl
+ implements HTMLPreElement
+{
+
+ private static final long serialVersionUID = -4195360849946217644L;
+
+ public int getWidth()
+ {
+ return getInteger( getAttribute( "width" ) );
+ }
+
+
+ public void setWidth( int width )
+ {
+ setAttribute( "width", String.valueOf( width ) );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLPreElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLQuoteElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLQuoteElementImpl.java
new file mode 100644
index 0000000..3a50b56
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLQuoteElementImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLQuoteElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLQuoteElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLQuoteElementImpl
+ extends HTMLElementImpl
+ implements HTMLQuoteElement
+{
+
+ private static final long serialVersionUID = -67544811597906132L;
+
+ public String getCite()
+ {
+ return getAttribute( "cite" );
+ }
+
+
+ public void setCite( String cite )
+ {
+ setAttribute( "cite", cite );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLQuoteElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLScriptElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLScriptElementImpl.java
new file mode 100644
index 0000000..75acfc9
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLScriptElementImpl.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+import org.w3c.dom.html.HTMLScriptElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLScriptElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLScriptElementImpl
+ extends HTMLElementImpl
+ implements HTMLScriptElement
+{
+
+ private static final long serialVersionUID = 5090330049085326558L;
+
+ public String getText()
+ {
+ Node child;
+ StringBuffer text = new StringBuffer();
+
+ // Find the Text nodes contained within this element and return their
+ // concatenated value. Required to go around comments, entities, etc.
+ child = getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof Text ) {
+ text.append(( (Text) child ).getData());
+ }
+ child = child.getNextSibling();
+ }
+ return text.toString();
+ }
+
+
+ public void setText( String text )
+ {
+ Node child;
+ Node next;
+
+ // Delete all the nodes and replace them with a single Text node.
+ // This is the only approach that can handle comments and other nodes.
+ child = getFirstChild();
+ while ( child != null )
+ {
+ next = child.getNextSibling();
+ removeChild( child );
+ child = next;
+ }
+ insertBefore( getOwnerDocument().createTextNode( text ), getFirstChild() );
+ }
+
+
+ public String getHtmlFor()
+ {
+ return getAttribute( "for" );
+ }
+
+
+ public void setHtmlFor( String htmlFor )
+ {
+ setAttribute( "for", htmlFor );
+ }
+
+
+ public String getEvent()
+ {
+ return getAttribute( "event" );
+ }
+
+
+ public void setEvent( String event )
+ {
+ setAttribute( "event", event );
+ }
+
+ public String getCharset()
+ {
+ return getAttribute( "charset" );
+ }
+
+
+ public void setCharset( String charset )
+ {
+ setAttribute( "charset", charset );
+ }
+
+
+ public boolean getDefer()
+ {
+ return getBinary( "defer" );
+ }
+
+
+ public void setDefer( boolean defer )
+ {
+ setAttribute( "defer", defer );
+ }
+
+
+ public String getSrc()
+ {
+ return getAttribute( "src" );
+ }
+
+
+ public void setSrc( String src )
+ {
+ setAttribute( "src", src );
+ }
+
+
+ public String getType()
+ {
+ return getAttribute( "type" );
+ }
+
+
+ public void setType( String type )
+ {
+ setAttribute( "type", type );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLScriptElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLSelectElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLSelectElementImpl.java
new file mode 100644
index 0000000..8095f02
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLSelectElementImpl.java
@@ -0,0 +1,233 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.html.HTMLCollection;
+import org.w3c.dom.html.HTMLElement;
+import org.w3c.dom.html.HTMLOptionElement;
+import org.w3c.dom.html.HTMLSelectElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLSelectElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLSelectElementImpl
+ extends HTMLElementImpl
+ implements HTMLSelectElement, HTMLFormControl
+{
+
+ private static final long serialVersionUID = -6998282711006968187L;
+
+ public String getType()
+ {
+ return getAttribute( "type" );
+ }
+
+
+ public String getValue()
+ {
+ return getAttribute( "value" );
+ }
+
+
+ public void setValue( String value )
+ {
+ setAttribute( "value", value );
+ }
+
+
+ public int getSelectedIndex()
+ {
+ NodeList options;
+ int i;
+
+ // Use getElementsByTagName() which creates a snapshot of all the
+ // OPTION elements under this SELECT. Access to the returned NodeList
+ // is very fast and the snapshot solves many synchronization problems.
+ // Locate the first selected OPTION and return its index. Note that
+ // the OPTION might be under an OPTGROUP.
+ options = getElementsByTagName( "OPTION" );
+ for ( i = 0 ; i < options.getLength() ; ++i )
+ if ( ( (HTMLOptionElement) options.item( i ) ).getSelected() )
+ return i;
+ return -1;
+ }
+
+
+ public void setSelectedIndex( int selectedIndex )
+ {
+ NodeList options;
+ int i;
+
+ // Use getElementsByTagName() which creates a snapshot of all the
+ // OPTION elements under this SELECT. Access to the returned NodeList
+ // is very fast and the snapshot solves many synchronization problems.
+ // Change the select so all OPTIONs are off, except for the
+ // selectIndex-th one.
+ options = getElementsByTagName( "OPTION" );
+ for ( i = 0 ; i < options.getLength() ; ++i )
+ ( (HTMLOptionElementImpl) options.item( i ) ).setSelected( i == selectedIndex );
+ }
+
+
+ public HTMLCollection getOptions()
+ {
+ if ( _options == null )
+ _options = new HTMLCollectionImpl( this, HTMLCollectionImpl.OPTION );
+ return _options;
+ }
+
+
+ public int getLength()
+ {
+ return getOptions().getLength();
+ }
+
+
+ public boolean getDisabled()
+ {
+ return getBinary( "disabled" );
+ }
+
+
+ public void setDisabled( boolean disabled )
+ {
+ setAttribute( "disabled", disabled );
+ }
+
+
+ public boolean getMultiple()
+ {
+ return getBinary( "multiple" );
+ }
+
+
+ public void setMultiple( boolean multiple )
+ {
+ setAttribute( "multiple", multiple );
+ }
+
+
+ public String getName()
+ {
+ return getAttribute( "name" );
+ }
+
+
+ public void setName( String name )
+ {
+ setAttribute( "name", name );
+ }
+
+
+ public int getSize()
+ {
+ return getInteger( getAttribute( "size" ) );
+ }
+
+
+ public void setSize( int size )
+ {
+ setAttribute( "size", String.valueOf( size ) );
+ }
+
+
+ public int getTabIndex()
+ {
+ return getInteger( getAttribute( "tabindex" ) );
+ }
+
+
+ public void setTabIndex( int tabIndex )
+ {
+ setAttribute( "tabindex", String.valueOf( tabIndex ) );
+ }
+
+
+ public void add( HTMLElement element, HTMLElement before )
+ {
+ insertBefore( element, before );
+ }
+
+
+ public void remove( int index )
+ {
+ NodeList options;
+ Node removed;
+
+ // Use getElementsByTagName() which creates a snapshot of all the
+ // OPTION elements under this SELECT. Access to the returned NodeList
+ // is very fast and the snapshot solves many synchronization problems.
+ // Remove the indexed OPTION from it's parent, this might be this
+ // SELECT or an OPTGROUP.
+ options = getElementsByTagName( "OPTION" );
+ removed = options.item( index );
+ if ( removed != null )
+ removed.getParentNode().removeChild ( removed );
+ }
+
+
+ public void blur()
+ {
+ // No scripting in server-side DOM. This method is moot.
+ }
+
+
+ public void focus()
+ {
+ // No scripting in server-side DOM. This method is moot.
+ }
+
+ /**
+ * Explicit implementation of getChildNodes() to avoid problems with
+ * overriding the getLength() method hidden in the super class.
+ */
+ public NodeList getChildNodes() {
+ return getChildNodesUnoptimized();
+ }
+
+ /**
+ * Explicit implementation of cloneNode() to ensure that cache used
+ * for getOptions() gets cleared.
+ */
+ public Node cloneNode(boolean deep) {
+ HTMLSelectElementImpl clonedNode = (HTMLSelectElementImpl)super.cloneNode( deep );
+ clonedNode._options = null;
+ return clonedNode;
+ }
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLSelectElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+ private HTMLCollection _options;
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLStyleElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLStyleElementImpl.java
new file mode 100644
index 0000000..3ce4b69
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLStyleElementImpl.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLStyleElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLStyleElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLStyleElementImpl
+ extends HTMLElementImpl
+ implements HTMLStyleElement
+{
+
+ private static final long serialVersionUID = -9001815754196124532L;
+
+ public boolean getDisabled()
+ {
+ return getBinary( "disabled" );
+ }
+
+
+ public void setDisabled( boolean disabled )
+ {
+ setAttribute( "disabled", disabled );
+ }
+
+
+ public String getMedia()
+ {
+ return getAttribute( "media" );
+ }
+
+
+ public void setMedia( String media )
+ {
+ setAttribute( "media", media );
+ }
+
+
+ public String getType()
+ {
+ return getAttribute( "type" );
+ }
+
+
+ public void setType( String type )
+ {
+ setAttribute( "type", type );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLStyleElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLTableCaptionElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLTableCaptionElementImpl.java
new file mode 100644
index 0000000..f604f62
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLTableCaptionElementImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLTableCaptionElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLTableCaptionElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLTableCaptionElementImpl
+ extends HTMLElementImpl
+ implements HTMLTableCaptionElement
+{
+
+ private static final long serialVersionUID = 183703024771848940L;
+
+ public String getAlign()
+ {
+ return getAttribute( "align" );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLTableCaptionElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLTableCellElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLTableCellElementImpl.java
new file mode 100644
index 0000000..cd4df94
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLTableCellElementImpl.java
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.html.HTMLTableCellElement;
+import org.w3c.dom.html.HTMLTableRowElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLTableCellElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLTableCellElementImpl
+ extends HTMLElementImpl
+ implements HTMLTableCellElement
+{
+
+ private static final long serialVersionUID = -2406518157464313922L;
+
+ public int getCellIndex()
+ {
+ Node parent;
+ Node child;
+ int index;
+
+ parent = getParentNode();
+ index = 0;
+ if ( parent instanceof HTMLTableRowElement )
+ {
+ child = parent.getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof HTMLTableCellElement )
+ {
+ if ( child == this )
+ return index;
+ ++ index;
+ }
+ child = child.getNextSibling();
+ }
+ }
+ return -1;
+ }
+
+
+ public void setCellIndex( int cellIndex )
+ {
+ Node parent;
+ Node child;
+
+ parent = getParentNode();
+ if ( parent instanceof HTMLTableRowElement )
+ {
+ child = parent.getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof HTMLTableCellElement )
+ {
+ if ( cellIndex == 0 )
+ {
+ if ( this != child )
+ parent.insertBefore( this, child );
+ return;
+ }
+ -- cellIndex;
+ }
+ child = child.getNextSibling();
+ }
+ }
+ parent.appendChild( this );
+ }
+
+
+ public String getAbbr()
+ {
+ return getAttribute( "abbr" );
+ }
+
+
+ public void setAbbr( String abbr )
+ {
+ setAttribute( "abbr", abbr );
+ }
+
+
+ public String getAlign()
+ {
+ return capitalize( getAttribute( "align" ) );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ public String getAxis()
+ {
+ return getAttribute( "axis" );
+ }
+
+
+ public void setAxis( String axis )
+ {
+ setAttribute( "axis", axis );
+ }
+
+ public String getBgColor()
+ {
+ return getAttribute( "bgcolor" );
+ }
+
+
+ public void setBgColor( String bgColor )
+ {
+ setAttribute( "bgcolor", bgColor );
+ }
+
+
+ public String getCh()
+ {
+ String ch;
+
+ // Make sure that the access key is a single character.
+ ch = getAttribute( "char" );
+ if ( ch != null && ch.length() > 1 )
+ ch = ch.substring( 0, 1 );
+ return ch;
+ }
+
+
+ public void setCh( String ch )
+ {
+ // Make sure that the access key is a single character.
+ if ( ch != null && ch.length() > 1 )
+ ch = ch.substring( 0, 1 );
+ setAttribute( "char", ch );
+ }
+
+
+ public String getChOff()
+ {
+ return getAttribute( "charoff" );
+ }
+
+
+ public void setChOff( String chOff )
+ {
+ setAttribute( "charoff", chOff );
+ }
+
+
+ public int getColSpan()
+ {
+ return getInteger( getAttribute( "colspan" ) );
+ }
+
+
+ public void setColSpan( int colspan )
+ {
+ setAttribute( "colspan", String.valueOf( colspan ) );
+ }
+
+
+ public String getHeaders()
+ {
+ return getAttribute( "headers" );
+ }
+
+
+ public void setHeaders( String headers )
+ {
+ setAttribute( "headers", headers );
+ }
+
+
+ public String getHeight()
+ {
+ return getAttribute( "height" );
+ }
+
+
+ public void setHeight( String height )
+ {
+ setAttribute( "height", height );
+ }
+
+
+ public boolean getNoWrap()
+ {
+ return getBinary( "nowrap" );
+ }
+
+
+ public void setNoWrap( boolean noWrap )
+ {
+ setAttribute( "nowrap", noWrap );
+ }
+
+ public int getRowSpan()
+ {
+ return getInteger( getAttribute( "rowspan" ) );
+ }
+
+
+ public void setRowSpan( int rowspan )
+ {
+ setAttribute( "rowspan", String.valueOf( rowspan ) );
+ }
+
+
+ public String getScope()
+ {
+ return getAttribute( "scope" );
+ }
+
+
+ public void setScope( String scope )
+ {
+ setAttribute( "scope", scope );
+ }
+
+
+ public String getVAlign()
+ {
+ return capitalize( getAttribute( "valign" ) );
+ }
+
+
+ public void setVAlign( String vAlign )
+ {
+ setAttribute( "valign", vAlign );
+ }
+
+
+ public String getWidth()
+ {
+ return getAttribute( "width" );
+ }
+
+
+ public void setWidth( String width )
+ {
+ setAttribute( "width", width );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLTableCellElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLTableColElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLTableColElementImpl.java
new file mode 100644
index 0000000..ce7d1d9
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLTableColElementImpl.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLTableColElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLTableColElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLTableColElementImpl
+ extends HTMLElementImpl
+ implements HTMLTableColElement
+{
+
+ private static final long serialVersionUID = -6189626162811911792L;
+
+ public String getAlign()
+ {
+ return capitalize( getAttribute( "align" ) );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ public String getCh()
+ {
+ String ch;
+
+ // Make sure that the access key is a single character.
+ ch = getAttribute( "char" );
+ if ( ch != null && ch.length() > 1 )
+ ch = ch.substring( 0, 1 );
+ return ch;
+ }
+
+
+ public void setCh( String ch )
+ {
+ // Make sure that the access key is a single character.
+ if ( ch != null && ch.length() > 1 )
+ ch = ch.substring( 0, 1 );
+ setAttribute( "char", ch );
+ }
+
+
+ public String getChOff()
+ {
+ return getAttribute( "charoff" );
+ }
+
+
+ public void setChOff( String chOff )
+ {
+ setAttribute( "charoff", chOff );
+ }
+
+
+ public int getSpan()
+ {
+ return getInteger( getAttribute( "span" ) );
+ }
+
+
+ public void setSpan( int span )
+ {
+ setAttribute( "span", String.valueOf( span ) );
+ }
+
+
+ public String getVAlign()
+ {
+ return capitalize( getAttribute( "valign" ) );
+ }
+
+
+ public void setVAlign( String vAlign )
+ {
+ setAttribute( "valign", vAlign );
+ }
+
+ public String getWidth()
+ {
+ return getAttribute( "width" );
+ }
+
+
+ public void setWidth( String width )
+ {
+ setAttribute( "width", width );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLTableColElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLTableElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLTableElementImpl.java
new file mode 100644
index 0000000..b3cc95e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLTableElementImpl.java
@@ -0,0 +1,409 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.html.HTMLCollection;
+import org.w3c.dom.html.HTMLElement;
+import org.w3c.dom.html.HTMLTableCaptionElement;
+import org.w3c.dom.html.HTMLTableElement;
+import org.w3c.dom.html.HTMLTableRowElement;
+import org.w3c.dom.html.HTMLTableSectionElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLAnchorElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLTableElementImpl
+ extends HTMLElementImpl
+ implements HTMLTableElement
+{
+
+ private static final long serialVersionUID = -1824053099870917532L;
+
+ public synchronized HTMLTableCaptionElement getCaption()
+ {
+ Node child;
+
+ child = getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof HTMLTableCaptionElement &&
+ child.getNodeName().equals( "CAPTION" ) )
+ return (HTMLTableCaptionElement) child;
+ child = child.getNextSibling();
+ }
+ return null;
+ }
+
+
+ public synchronized void setCaption( HTMLTableCaptionElement caption )
+ {
+ if ( caption != null && ! caption.getTagName().equals( "CAPTION" ) )
+ throw new IllegalArgumentException( "HTM016 Argument 'caption' is not an element of type ." );
+ deleteCaption();
+ if ( caption != null )
+ appendChild( caption );
+ }
+
+
+ public synchronized HTMLElement createCaption()
+ {
+ HTMLElement section;
+
+ section = getCaption();
+ if ( section != null )
+ return section;
+ section = new HTMLTableCaptionElementImpl( (HTMLDocumentImpl) getOwnerDocument(), "CAPTION" );
+ appendChild( section );
+ return section;
+ }
+
+
+ public synchronized void deleteCaption()
+ {
+ Node old;
+
+ old = getCaption();
+ if ( old != null )
+ removeChild ( old );
+ }
+
+ public synchronized HTMLTableSectionElement getTHead()
+ {
+ Node child;
+
+ child = getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof HTMLTableSectionElement &&
+ child.getNodeName().equals( "THEAD" ) )
+ return (HTMLTableSectionElement) child;
+ child = child.getNextSibling();
+ }
+ return null;
+ }
+
+
+ public synchronized void setTHead( HTMLTableSectionElement tHead )
+ {
+ if ( tHead != null && ! tHead.getTagName().equals( "THEAD" ) )
+ throw new IllegalArgumentException( "HTM017 Argument 'tHead' is not an element of type ." );
+ deleteTHead();
+ if ( tHead != null )
+ appendChild( tHead );
+ }
+
+
+ public synchronized HTMLElement createTHead()
+ {
+ HTMLElement section;
+
+ section = getTHead();
+ if ( section != null )
+ return section;
+ section = new HTMLTableSectionElementImpl( (HTMLDocumentImpl) getOwnerDocument(), "THEAD" );
+ appendChild( section );
+ return section;
+ }
+
+
+ public synchronized void deleteTHead()
+ {
+ Node old;
+
+ old = getTHead();
+ if ( old != null )
+ removeChild ( old );
+ }
+
+ public synchronized HTMLTableSectionElement getTFoot()
+ {
+ Node child;
+
+ child = getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof HTMLTableSectionElement &&
+ child.getNodeName().equals( "TFOOT" ) )
+ return (HTMLTableSectionElement) child;
+ child = child.getNextSibling();
+ }
+ return null;
+ }
+
+
+ public synchronized void setTFoot( HTMLTableSectionElement tFoot )
+ {
+ if ( tFoot != null && ! tFoot.getTagName().equals( "TFOOT" ) )
+ throw new IllegalArgumentException( "HTM018 Argument 'tFoot' is not an element of type ." );
+ deleteTFoot();
+ if ( tFoot != null )
+ appendChild( tFoot );
+ }
+
+
+ public synchronized HTMLElement createTFoot()
+ {
+ HTMLElement section;
+
+ section = getTFoot();
+ if ( section != null )
+ return section;
+ section = new HTMLTableSectionElementImpl( (HTMLDocumentImpl) getOwnerDocument(), "TFOOT" );
+ appendChild( section );
+ return section;
+ }
+
+
+ public synchronized void deleteTFoot()
+ {
+ Node old;
+
+ old = getTFoot();
+ if ( old != null )
+ removeChild ( old );
+ }
+
+ public HTMLCollection getRows()
+ {
+ if ( _rows == null )
+ _rows = new HTMLCollectionImpl( this, HTMLCollectionImpl.ROW );
+ return _rows;
+ }
+
+
+ public HTMLCollection getTBodies()
+ {
+ if ( _bodies == null )
+ _bodies = new HTMLCollectionImpl( this, HTMLCollectionImpl.TBODY );
+ return _bodies;
+ }
+
+
+ public String getAlign()
+ {
+ return capitalize( getAttribute( "align" ) );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ public String getBgColor()
+ {
+ return getAttribute( "bgcolor" );
+ }
+
+
+ public void setBgColor( String bgColor )
+ {
+ setAttribute( "bgcolor", bgColor );
+ }
+
+
+ public String getBorder()
+ {
+ return getAttribute( "border" );
+ }
+
+
+ public void setBorder( String border )
+ {
+ setAttribute( "border", border );
+ }
+
+
+ public String getCellPadding()
+ {
+ return getAttribute( "cellpadding" );
+ }
+
+
+ public void setCellPadding( String cellPadding )
+ {
+ setAttribute( "cellpadding", cellPadding );
+ }
+
+
+ public String getCellSpacing()
+ {
+ return getAttribute( "cellspacing" );
+ }
+
+
+ public void setCellSpacing( String cellSpacing )
+ {
+ setAttribute( "cellspacing", cellSpacing );
+ }
+
+
+ public String getFrame()
+ {
+ return capitalize( getAttribute( "frame" ) );
+ }
+
+
+ public void setFrame( String frame )
+ {
+ setAttribute( "frame", frame );
+ }
+
+
+ public String getRules()
+ {
+ return capitalize( getAttribute( "rules" ) );
+ }
+
+
+ public void setRules( String rules )
+ {
+ setAttribute( "rules", rules );
+ }
+
+
+ public String getSummary()
+ {
+ return getAttribute( "summary" );
+ }
+
+
+ public void setSummary( String summary )
+ {
+ setAttribute( "summary", summary );
+ }
+
+
+ public String getWidth()
+ {
+ return getAttribute( "width" );
+ }
+
+
+ public void setWidth( String width )
+ {
+ setAttribute( "width", width );
+ }
+
+
+ public HTMLElement insertRow( int index )
+ {
+ HTMLTableRowElementImpl newRow;
+
+ newRow = new HTMLTableRowElementImpl( (HTMLDocumentImpl) getOwnerDocument(), "TR" );
+ //newRow.insertCell( 0 );
+ insertRowX( index, newRow );
+ return newRow;
+ }
+
+
+ void insertRowX( int index, HTMLTableRowElementImpl newRow )
+ {
+ Node child;
+ Node lastSection = null;
+
+ child = getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof HTMLTableRowElement )
+ {
+ if ( index == 0 )
+ {
+ insertBefore( newRow, child );
+ return;
+ }
+ }
+ else
+ if ( child instanceof HTMLTableSectionElementImpl )
+ {
+ lastSection = child;
+ index = ( (HTMLTableSectionElementImpl) child ).insertRowX( index, newRow );
+ if ( index < 0 )
+ return;
+ }
+ child = child.getNextSibling();
+ }
+ if ( lastSection != null )
+ lastSection.appendChild( newRow );
+ else
+ appendChild( newRow );
+ }
+
+
+ public synchronized void deleteRow( int index )
+ {
+ Node child;
+
+ child = getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof HTMLTableRowElement )
+ {
+ if ( index == 0 )
+ {
+ removeChild ( child );
+ return;
+ }
+ --index;
+ }
+ else
+ if ( child instanceof HTMLTableSectionElementImpl )
+ {
+ index = ( (HTMLTableSectionElementImpl) child ).deleteRowX( index );
+ if ( index < 0 )
+ return;
+ }
+ child = child.getNextSibling();
+ }
+ }
+
+ /**
+ * Explicit implementation of cloneNode() to ensure that cache used
+ * for getRows() and getTBodies() gets cleared.
+ */
+ public Node cloneNode( boolean deep ) {
+ HTMLTableElementImpl clonedNode = (HTMLTableElementImpl)super.cloneNode( deep );
+ clonedNode._rows = null;
+ clonedNode._bodies = null;
+ return clonedNode;
+ }
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLTableElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+ private HTMLCollectionImpl _rows;
+
+
+ private HTMLCollectionImpl _bodies;
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLTableRowElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLTableRowElementImpl.java
new file mode 100644
index 0000000..b021c1f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLTableRowElementImpl.java
@@ -0,0 +1,276 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.html.HTMLCollection;
+import org.w3c.dom.html.HTMLElement;
+import org.w3c.dom.html.HTMLTableCellElement;
+import org.w3c.dom.html.HTMLTableElement;
+import org.w3c.dom.html.HTMLTableRowElement;
+import org.w3c.dom.html.HTMLTableSectionElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLTableRowElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLTableRowElementImpl
+ extends HTMLElementImpl
+ implements HTMLTableRowElement
+{
+
+ private static final long serialVersionUID = 5409562635656244263L;
+
+ public int getRowIndex()
+ {
+ Node parent;
+
+ parent = getParentNode();
+ if ( parent instanceof HTMLTableSectionElement ) {
+ parent = parent.getParentNode();
+ }
+ if ( parent instanceof HTMLTableElement ) {
+ return getRowIndex( parent );
+ }
+ return -1;
+ }
+
+
+ public void setRowIndex( int rowIndex )
+ {
+ Node parent;
+
+ parent = getParentNode();
+ if ( parent instanceof HTMLTableSectionElement ) {
+ parent = parent.getParentNode();
+ }
+ if ( parent instanceof HTMLTableElement ) {
+ ( (HTMLTableElementImpl) parent ).insertRowX( rowIndex, this );
+ }
+ }
+
+
+ public int getSectionRowIndex()
+ {
+ Node parent;
+
+ parent = getParentNode();
+ if ( parent instanceof HTMLTableSectionElement ) {
+ return getRowIndex( parent );
+ }
+ return -1;
+ }
+
+
+ public void setSectionRowIndex( int sectionRowIndex )
+ {
+ Node parent;
+
+ parent = getParentNode();
+ if ( parent instanceof HTMLTableSectionElement ) {
+ ( (HTMLTableSectionElementImpl) parent ).insertRowX( sectionRowIndex, this );
+ }
+ }
+
+
+ int getRowIndex( Node parent )
+ {
+ NodeList rows;
+ int i;
+
+ // Use getElementsByTagName() which creates a snapshot of all the
+ // TR elements under the TABLE/section. Access to the returned NodeList
+ // is very fast and the snapshot solves many synchronization problems.
+ rows = ( (HTMLElement) parent ).getElementsByTagName( "TR" );
+ for ( i = 0 ; i < rows.getLength() ; ++i ) {
+ if ( rows.item( i ) == this ) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+
+ public HTMLCollection getCells()
+ {
+ if ( _cells == null ) {
+ _cells = new HTMLCollectionImpl( this, HTMLCollectionImpl.CELL );
+ }
+ return _cells;
+ }
+
+
+ public void setCells( HTMLCollection cells )
+ {
+ Node child;
+ int i;
+
+ child = getFirstChild();
+ while ( child != null ) {
+ removeChild( child );
+ child = child.getNextSibling();
+ }
+ i = 0;
+ child = cells.item( i );
+ while ( child != null ) {
+ appendChild ( child );
+ ++i;
+ child = cells.item( i );
+ }
+ }
+
+
+ public HTMLElement insertCell( int index )
+ {
+ Node child;
+ HTMLElement newCell;
+
+ newCell = new HTMLTableCellElementImpl( (HTMLDocumentImpl) getOwnerDocument(), "TD" );
+ child = getFirstChild();
+ while ( child != null ) {
+ if ( child instanceof HTMLTableCellElement ) {
+ if ( index == 0 ) {
+ insertBefore( newCell, child );
+ return newCell;
+ }
+ --index;
+ }
+ child = child.getNextSibling();
+ }
+ appendChild( newCell );
+ return newCell;
+ }
+
+
+ public void deleteCell( int index )
+ {
+ Node child;
+
+ child = getFirstChild();
+ while ( child != null ) {
+ if ( child instanceof HTMLTableCellElement ) {
+ if ( index == 0 ) {
+ removeChild ( child );
+ return;
+ }
+ --index;
+ }
+ child = child.getNextSibling();
+ }
+ }
+
+
+ public String getAlign()
+ {
+ return capitalize( getAttribute( "align" ) );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ public String getBgColor()
+ {
+ return getAttribute( "bgcolor" );
+ }
+
+
+ public void setBgColor( String bgColor )
+ {
+ setAttribute( "bgcolor", bgColor );
+ }
+
+
+ public String getCh()
+ {
+ String ch;
+
+ // Make sure that the access key is a single character.
+ ch = getAttribute( "char" );
+ if ( ch != null && ch.length() > 1 ) {
+ ch = ch.substring( 0, 1 );
+ }
+ return ch;
+ }
+
+
+ public void setCh( String ch )
+ {
+ // Make sure that the access key is a single character.
+ if ( ch != null && ch.length() > 1 ) {
+ ch = ch.substring( 0, 1 );
+ }
+ setAttribute( "char", ch );
+ }
+
+
+ public String getChOff()
+ {
+ return getAttribute( "charoff" );
+ }
+
+
+ public void setChOff( String chOff )
+ {
+ setAttribute( "charoff", chOff );
+ }
+
+
+ public String getVAlign()
+ {
+ return capitalize( getAttribute( "valign" ) );
+ }
+
+
+ public void setVAlign( String vAlign )
+ {
+ setAttribute( "valign", vAlign );
+ }
+
+ /**
+ * Explicit implementation of cloneNode() to ensure that cache used
+ * for getCells() gets cleared.
+ */
+ public Node cloneNode( boolean deep ) {
+ HTMLTableRowElementImpl clonedNode = (HTMLTableRowElementImpl)super.cloneNode( deep );
+ clonedNode._cells = null;
+ return clonedNode;
+ }
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLTableRowElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+ HTMLCollection _cells;
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLTableSectionElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLTableSectionElementImpl.java
new file mode 100644
index 0000000..030ab08
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLTableSectionElementImpl.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.html.HTMLCollection;
+import org.w3c.dom.html.HTMLElement;
+import org.w3c.dom.html.HTMLTableRowElement;
+import org.w3c.dom.html.HTMLTableSectionElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLTableSectionElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLTableSectionElementImpl
+ extends HTMLElementImpl
+ implements HTMLTableSectionElement
+{
+
+ private static final long serialVersionUID = 1016412997716618027L;
+
+ public String getAlign()
+ {
+ return capitalize( getAttribute( "align" ) );
+ }
+
+
+ public void setAlign( String align )
+ {
+ setAttribute( "align", align );
+ }
+
+
+ public String getCh()
+ {
+ String ch;
+
+ // Make sure that the access key is a single character.
+ ch = getAttribute( "char" );
+ if ( ch != null && ch.length() > 1 )
+ ch = ch.substring( 0, 1 );
+ return ch;
+ }
+
+
+ public void setCh( String ch )
+ {
+ // Make sure that the access key is a single character.
+ if ( ch != null && ch.length() > 1 )
+ ch = ch.substring( 0, 1 );
+ setAttribute( "char", ch );
+ }
+
+
+ public String getChOff()
+ {
+ return getAttribute( "charoff" );
+ }
+
+
+ public void setChOff( String chOff )
+ {
+ setAttribute( "charoff", chOff );
+ }
+
+
+ public String getVAlign()
+ {
+ return capitalize( getAttribute( "valign" ) );
+ }
+
+
+ public void setVAlign( String vAlign )
+ {
+ setAttribute( "valign", vAlign );
+ }
+
+
+ public HTMLCollection getRows()
+ {
+ if ( _rows == null )
+ _rows = new HTMLCollectionImpl( this, HTMLCollectionImpl.ROW );
+ return _rows;
+ }
+
+
+ public HTMLElement insertRow( int index )
+ {
+ HTMLTableRowElementImpl newRow;
+
+ newRow = new HTMLTableRowElementImpl( (HTMLDocumentImpl) getOwnerDocument(), "TR" );
+ newRow.insertCell( 0 );
+ if ( insertRowX( index, newRow ) >= 0 )
+ appendChild( newRow );
+ return newRow;
+ }
+
+
+ int insertRowX( int index, HTMLTableRowElementImpl newRow )
+ {
+ Node child;
+
+ child = getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof HTMLTableRowElement )
+ {
+ if ( index == 0 )
+ {
+ insertBefore( newRow, child );
+ return -1;
+ }
+ --index;
+ }
+ child = child.getNextSibling();
+ }
+ return index;
+ }
+
+
+ public void deleteRow( int index )
+ {
+ deleteRowX( index );
+ }
+
+
+ int deleteRowX( int index )
+ {
+ Node child;
+
+ child = getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof HTMLTableRowElement )
+ {
+ if ( index == 0 )
+ {
+ removeChild ( child );
+ return -1;
+ }
+ --index;
+ }
+ child = child.getNextSibling();
+ }
+ return index;
+ }
+
+ /**
+ * Explicit implementation of cloneNode() to ensure that cache used
+ * for getRows() gets cleared.
+ */
+ public Node cloneNode( boolean deep ) {
+ HTMLTableSectionElementImpl clonedNode = (HTMLTableSectionElementImpl)super.cloneNode( deep );
+ clonedNode._rows = null;
+ return clonedNode;
+ }
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLTableSectionElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+ private HTMLCollectionImpl _rows;
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLTextAreaElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLTextAreaElementImpl.java
new file mode 100644
index 0000000..2837a2e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLTextAreaElementImpl.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLTextAreaElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLTextAreaElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLTextAreaElementImpl
+ extends HTMLElementImpl
+ implements HTMLTextAreaElement, HTMLFormControl
+{
+
+ private static final long serialVersionUID = -6737778308542678104L;
+
+ public String getDefaultValue()
+ {
+ // ! NOT FULLY IMPLEMENTED !
+ return getAttribute( "default-value" );
+ }
+
+
+ public void setDefaultValue( String defaultValue )
+ {
+ // ! NOT FULLY IMPLEMENTED !
+ setAttribute( "default-value", defaultValue );
+ }
+
+
+
+ public String getAccessKey()
+ {
+ String accessKey;
+
+ // Make sure that the access key is a single character.
+ accessKey = getAttribute( "accesskey" );
+ if ( accessKey != null && accessKey.length() > 1 )
+ accessKey = accessKey.substring( 0, 1 );
+ return accessKey;
+ }
+
+
+ public void setAccessKey( String accessKey )
+ {
+ // Make sure that the access key is a single character.
+ if ( accessKey != null && accessKey.length() > 1 )
+ accessKey = accessKey.substring( 0, 1 );
+ setAttribute( "accesskey", accessKey );
+ }
+
+
+ public int getCols()
+ {
+ return getInteger( getAttribute( "cols" ) );
+ }
+
+
+ public void setCols( int cols )
+ {
+ setAttribute( "cols", String.valueOf( cols ) );
+ }
+
+
+ public boolean getDisabled()
+ {
+ return getBinary( "disabled" );
+ }
+
+
+ public void setDisabled( boolean disabled )
+ {
+ setAttribute( "disabled", disabled );
+ }
+
+
+ public String getName()
+ {
+ return getAttribute( "name" );
+ }
+
+
+ public void setName( String name )
+ {
+ setAttribute( "name", name );
+ }
+
+
+ public boolean getReadOnly()
+ {
+ return getBinary( "readonly" );
+ }
+
+
+ public void setReadOnly( boolean readOnly )
+ {
+ setAttribute( "readonly", readOnly );
+ }
+
+
+ public int getRows()
+ {
+ return getInteger( getAttribute( "rows" ) );
+ }
+
+
+ public void setRows( int rows )
+ {
+ setAttribute( "rows", String.valueOf( rows ) );
+ }
+
+
+ public int getTabIndex()
+ {
+ return getInteger( getAttribute( "tabindex" ) );
+ }
+
+
+ public void setTabIndex( int tabIndex )
+ {
+ setAttribute( "tabindex", String.valueOf( tabIndex ) );
+ }
+
+
+ public String getType()
+ {
+ return getAttribute( "type" );
+ }
+
+
+ public String getValue()
+ {
+ return getAttribute( "value" );
+ }
+
+
+ public void setValue( String value )
+ {
+ setAttribute( "value", value );
+ }
+
+
+ public void blur()
+ {
+ // No scripting in server-side DOM. This method is moot.
+ }
+
+
+ public void focus()
+ {
+ // No scripting in server-side DOM. This method is moot.
+ }
+
+
+ public void select()
+ {
+ // No scripting in server-side DOM. This method is moot.
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLTextAreaElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLTitleElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLTitleElementImpl.java
new file mode 100644
index 0000000..0e7bb3a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLTitleElementImpl.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+import org.w3c.dom.html.HTMLTitleElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLTitleElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLTitleElementImpl
+ extends HTMLElementImpl
+ implements HTMLTitleElement
+{
+
+ private static final long serialVersionUID = 879646303512367875L;
+
+ public String getText()
+ {
+ Node child;
+ StringBuffer text = new StringBuffer();
+
+ // Find the Text nodes contained within this element and return their
+ // concatenated value. Required to go around comments, entities, etc.
+ child = getFirstChild();
+ while ( child != null )
+ {
+ if ( child instanceof Text ) {
+ text.append(( (Text) child ).getData());
+ }
+ child = child.getNextSibling();
+ }
+ return text.toString();
+ }
+
+
+ public void setText( String text )
+ {
+ Node child;
+ Node next;
+
+ // Delete all the nodes and replace them with a single Text node.
+ // This is the only approach that can handle comments and other nodes.
+ child = getFirstChild();
+ while ( child != null )
+ {
+ next = child.getNextSibling();
+ removeChild( child );
+ child = next;
+ }
+ insertBefore( getOwnerDocument().createTextNode( text ), getFirstChild() );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLTitleElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/HTMLUListElementImpl.java b/resources/xerces2-j-src/org/apache/html/dom/HTMLUListElementImpl.java
new file mode 100644
index 0000000..ebb84d8
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/HTMLUListElementImpl.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.html.dom;
+
+import org.w3c.dom.html.HTMLUListElement;
+
+/**
+ * @xerces.internal
+ * @version $Revision$ $Date$
+ * @author Assaf Arkin
+ * @see org.w3c.dom.html.HTMLUListElement
+ * @see org.apache.xerces.dom.ElementImpl
+ */
+public class HTMLUListElementImpl
+ extends HTMLElementImpl
+ implements HTMLUListElement
+{
+
+ private static final long serialVersionUID = -3220401442015109211L;
+
+ public boolean getCompact()
+ {
+ return getBinary( "compact" );
+ }
+
+
+ public void setCompact( boolean compact )
+ {
+ setAttribute( "compact", compact );
+ }
+
+
+ public String getType()
+ {
+ return getAttribute( "type" );
+ }
+
+
+ public void setType( String type )
+ {
+ setAttribute( "type", type );
+ }
+
+
+ /**
+ * Constructor requires owner document.
+ *
+ * @param owner The owner HTML document
+ */
+ public HTMLUListElementImpl( HTMLDocumentImpl owner, String name )
+ {
+ super( owner, name );
+ }
+
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/html/dom/NameNodeListImpl.java b/resources/xerces2-j-src/org/apache/html/dom/NameNodeListImpl.java
new file mode 100644
index 0000000..225c07d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/NameNodeListImpl.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.html.dom;
+
+import org.apache.xerces.dom.DeepNodeListImpl;
+import org.apache.xerces.dom.ElementImpl;
+import org.apache.xerces.dom.NodeImpl;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * This class implements the DOM's NodeList behavior for
+ * HTMLDocuemnt.getElementsByName().
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ * @see DeepNodeListImpl
+ */
+public class NameNodeListImpl
+ extends DeepNodeListImpl
+ implements NodeList {
+
+
+ /** Constructor. */
+ public NameNodeListImpl(NodeImpl rootNode, String tagName) {
+ super( rootNode, tagName );
+ }
+
+
+ /**
+ * Iterative tree-walker. When you have a Parent link, there's often no
+ * need to resort to recursion. NOTE THAT only Element nodes are matched
+ * since we're specifically supporting getElementsByTagName().
+ */
+ protected Node nextMatchingElementAfter(Node current) {
+
+ Node next;
+ while (current != null) {
+ // Look down to first child.
+ if (current.hasChildNodes()) {
+ current = (current.getFirstChild());
+ }
+
+ // Look right to sibling (but not from root!)
+ else if (current != rootNode && null != (next = current.getNextSibling())) {
+ current = next;
+ }
+
+ // Look up and right (but not past root!)
+ else {
+ next = null;
+ for (; current != rootNode; // Stop when we return to starting point
+ current = current.getParentNode()) {
+
+ next = current.getNextSibling();
+ if (next != null)
+ break;
+ }
+ current = next;
+ }
+
+ // Have we found an Element with the right tagName?
+ // ("*" matches anything.)
+ if (current != rootNode && current != null
+ && current.getNodeType() == Node.ELEMENT_NODE ) {
+ String name = ((ElementImpl) current).getAttribute( "name" );
+ if ( name.equals("*") || name.equals(tagName))
+ return current;
+ }
+
+ // Otherwise continue walking the tree
+ }
+
+ // Fell out of tree-walk; no more instances found
+ return null;
+
+ } // nextMatchingElementAfter(int):Node
+
+} // class NameNodeListImpl
diff --git a/resources/xerces2-j-src/org/apache/html/dom/ObjectFactory.java b/resources/xerces2-j-src/org/apache/html/dom/ObjectFactory.java
new file mode 100644
index 0000000..7a04cbe
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/ObjectFactory.java
@@ -0,0 +1,545 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.html.dom;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Properties;
+
+/**
+ * This class is duplicated for each JAXP subpackage so keep it in sync.
+ * It is package private and therefore is not exposed as part of the JAXP
+ * API.
+ *
+ * This code is designed to implement the JAXP 1.1 spec pluggability
+ * feature and is designed to run on JDK version 1.1 and
+ * later, and to compile on JDK 1.2 and onward.
+ * The code also runs both as part of an unbundled jar file and
+ * when bundled as part of the JDK.
+ *
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+final class ObjectFactory {
+
+ //
+ // Constants
+ //
+
+ // name of default properties file to look for in JDK's jre/lib directory
+ private static final String DEFAULT_PROPERTIES_FILENAME = "xerces.properties";
+
+ /** Set to true for debugging */
+ private static final boolean DEBUG = isDebugEnabled();
+
+ /**
+ * Default columns per line.
+ */
+ private static final int DEFAULT_LINE_LENGTH = 80;
+
+ /** cache the contents of the xerces.properties file.
+ * Until an attempt has been made to read this file, this will
+ * be null; if the file does not exist or we encounter some other error
+ * during the read, this will be empty.
+ */
+ private static Properties fXercesProperties = null;
+
+ /***
+ * Cache the time stamp of the xerces.properties file so
+ * that we know if it's been modified and can invalidate
+ * the cache when necessary.
+ */
+ private static long fLastModified = -1;
+
+ //
+ // static methods
+ //
+
+ /**
+ * Finds the implementation Class object in the specified order. The
+ * specified order is the following:
+ *
+ * - query the system property using
System.getProperty
+ * - read
META-INF/services/factoryId file
+ * - use fallback classname
+ *
+ *
+ * @return Class object of factory, never null
+ *
+ * @param factoryId Name of the factory to find, same as
+ * a property name
+ * @param fallbackClassName Implementation class name, if nothing else
+ * is found. Use null to mean no fallback.
+ *
+ * @exception ObjectFactory.ConfigurationError
+ */
+ static Object createObject(String factoryId, String fallbackClassName)
+ throws ConfigurationError {
+ return createObject(factoryId, null, fallbackClassName);
+ } // createObject(String,String):Object
+
+ /**
+ * Finds the implementation Class object in the specified order. The
+ * specified order is the following:
+ *
+ * - query the system property using
System.getProperty
+ * - read
$java.home/lib/propertiesFilename file
+ * - read
META-INF/services/factoryId file
+ * - use fallback classname
+ *
+ *
+ * @return Class object of factory, never null
+ *
+ * @param factoryId Name of the factory to find, same as
+ * a property name
+ * @param propertiesFilename The filename in the $java.home/lib directory
+ * of the properties file. If none specified,
+ * ${java.home}/lib/xerces.properties will be used.
+ * @param fallbackClassName Implementation class name, if nothing else
+ * is found. Use null to mean no fallback.
+ *
+ * @exception ObjectFactory.ConfigurationError
+ */
+ static Object createObject(String factoryId,
+ String propertiesFilename,
+ String fallbackClassName)
+ throws ConfigurationError
+ {
+ if (DEBUG) debugPrintln("debug is on");
+
+ ClassLoader cl = findClassLoader();
+
+ // Use the system property first
+ try {
+ String systemProp = SecuritySupport.getSystemProperty(factoryId);
+ if (systemProp != null && systemProp.length() > 0) {
+ if (DEBUG) debugPrintln("found system property, value=" + systemProp);
+ return newInstance(systemProp, cl, true);
+ }
+ } catch (SecurityException se) {
+ // Ignore and continue w/ next location
+ }
+
+ // Try to read from propertiesFilename, or $java.home/lib/xerces.properties
+ String factoryClassName = null;
+ // no properties file name specified; use $JAVA_HOME/lib/xerces.properties:
+ if (propertiesFilename == null) {
+ File propertiesFile = null;
+ boolean propertiesFileExists = false;
+ try {
+ String javah = SecuritySupport.getSystemProperty("java.home");
+ propertiesFilename = javah + File.separator +
+ "lib" + File.separator + DEFAULT_PROPERTIES_FILENAME;
+ propertiesFile = new File(propertiesFilename);
+ propertiesFileExists = SecuritySupport.getFileExists(propertiesFile);
+ } catch (SecurityException e) {
+ // try again...
+ fLastModified = -1;
+ fXercesProperties = null;
+ }
+
+ synchronized (ObjectFactory.class) {
+ boolean loadProperties = false;
+ FileInputStream fis = null;
+ try {
+ // file existed last time
+ if(fLastModified >= 0) {
+ if(propertiesFileExists &&
+ (fLastModified < (fLastModified = SecuritySupport.getLastModified(propertiesFile)))) {
+ loadProperties = true;
+ } else {
+ // file has stopped existing...
+ if(!propertiesFileExists) {
+ fLastModified = -1;
+ fXercesProperties = null;
+ } // else, file wasn't modified!
+ }
+ } else {
+ // file has started to exist:
+ if(propertiesFileExists) {
+ loadProperties = true;
+ fLastModified = SecuritySupport.getLastModified(propertiesFile);
+ } // else, nothing's changed
+ }
+ if(loadProperties) {
+ // must never have attempted to read xerces.properties before (or it's outdeated)
+ fXercesProperties = new Properties();
+ fis = SecuritySupport.getFileInputStream(propertiesFile);
+ fXercesProperties.load(fis);
+ }
+ } catch (Exception x) {
+ fXercesProperties = null;
+ fLastModified = -1;
+ // assert(x instanceof FileNotFoundException
+ // || x instanceof SecurityException)
+ // In both cases, ignore and continue w/ next location
+ }
+ finally {
+ // try to close the input stream if one was opened.
+ if (fis != null) {
+ try {
+ fis.close();
+ }
+ // Ignore the exception.
+ catch (IOException exc) {}
+ }
+ }
+ }
+ if(fXercesProperties != null) {
+ factoryClassName = fXercesProperties.getProperty(factoryId);
+ }
+ } else {
+ FileInputStream fis = null;
+ try {
+ fis = SecuritySupport.getFileInputStream(new File(propertiesFilename));
+ Properties props = new Properties();
+ props.load(fis);
+ factoryClassName = props.getProperty(factoryId);
+ } catch (Exception x) {
+ // assert(x instanceof FileNotFoundException
+ // || x instanceof SecurityException)
+ // In both cases, ignore and continue w/ next location
+ }
+ finally {
+ // try to close the input stream if one was opened.
+ if (fis != null) {
+ try {
+ fis.close();
+ }
+ // Ignore the exception.
+ catch (IOException exc) {}
+ }
+ }
+ }
+ if (factoryClassName != null) {
+ if (DEBUG) debugPrintln("found in " + propertiesFilename + ", value=" + factoryClassName);
+ return newInstance(factoryClassName, cl, true);
+ }
+
+ // Try Jar Service Provider Mechanism
+ Object provider = findJarServiceProvider(factoryId);
+ if (provider != null) {
+ return provider;
+ }
+
+ if (fallbackClassName == null) {
+ throw new ConfigurationError(
+ "Provider for " + factoryId + " cannot be found", null);
+ }
+
+ if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName);
+ return newInstance(fallbackClassName, cl, true);
+ } // createObject(String,String,String):Object
+
+ //
+ // Private static methods
+ //
+
+ /** Returns true if debug has been enabled. */
+ private static boolean isDebugEnabled() {
+ try {
+ String val = SecuritySupport.getSystemProperty("xerces.debug");
+ // Allow simply setting the prop to turn on debug
+ return (val != null && (!"false".equals(val)));
+ }
+ catch (SecurityException se) {}
+ return false;
+ } // isDebugEnabled()
+
+ /** Prints a message to standard error if debugging is enabled. */
+ private static void debugPrintln(String msg) {
+ if (DEBUG) {
+ System.err.println("XERCES: " + msg);
+ }
+ } // debugPrintln(String)
+
+ /**
+ * Figure out which ClassLoader to use. For JDK 1.2 and later use
+ * the context ClassLoader.
+ */
+ static ClassLoader findClassLoader()
+ throws ConfigurationError
+ {
+ // Figure out which ClassLoader to use for loading the provider
+ // class. If there is a Context ClassLoader then use it.
+ ClassLoader context = SecuritySupport.getContextClassLoader();
+ ClassLoader system = SecuritySupport.getSystemClassLoader();
+
+ ClassLoader chain = system;
+ while (true) {
+ if (context == chain) {
+ // Assert: we are on JDK 1.1 or we have no Context ClassLoader
+ // or any Context ClassLoader in chain of system classloader
+ // (including extension ClassLoader) so extend to widest
+ // ClassLoader (always look in system ClassLoader if Xerces
+ // is in boot/extension/system classpath and in current
+ // ClassLoader otherwise); normal classloaders delegate
+ // back to system ClassLoader first so this widening doesn't
+ // change the fact that context ClassLoader will be consulted
+ ClassLoader current = ObjectFactory.class.getClassLoader();
+
+ chain = system;
+ while (true) {
+ if (current == chain) {
+ // Assert: Current ClassLoader in chain of
+ // boot/extension/system ClassLoaders
+ return system;
+ }
+ if (chain == null) {
+ break;
+ }
+ chain = SecuritySupport.getParentClassLoader(chain);
+ }
+
+ // Assert: Current ClassLoader not in chain of
+ // boot/extension/system ClassLoaders
+ return current;
+ }
+
+ if (chain == null) {
+ // boot ClassLoader reached
+ break;
+ }
+
+ // Check for any extension ClassLoaders in chain up to
+ // boot ClassLoader
+ chain = SecuritySupport.getParentClassLoader(chain);
+ };
+
+ // Assert: Context ClassLoader not in chain of
+ // boot/extension/system ClassLoaders
+ return context;
+ } // findClassLoader():ClassLoader
+
+ /**
+ * Create an instance of a class using the specified ClassLoader
+ */
+ static Object newInstance(String className, ClassLoader cl,
+ boolean doFallback)
+ throws ConfigurationError
+ {
+ // assert(className != null);
+ try{
+ Class providerClass = findProviderClass(className, cl, doFallback);
+ Object instance = providerClass.newInstance();
+ if (DEBUG) debugPrintln("created new instance of " + providerClass +
+ " using ClassLoader: " + cl);
+ return instance;
+ } catch (ClassNotFoundException x) {
+ throw new ConfigurationError(
+ "Provider " + className + " not found", x);
+ } catch (Exception x) {
+ throw new ConfigurationError(
+ "Provider " + className + " could not be instantiated: " + x,
+ x);
+ }
+ }
+
+ /**
+ * Find a Class using the specified ClassLoader
+ */
+ static Class findProviderClass(String className, ClassLoader cl,
+ boolean doFallback)
+ throws ClassNotFoundException, ConfigurationError
+ {
+ //throw security exception if the calling thread is not allowed to access the package
+ //restrict the access to package as specified in java.security policy
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ final int lastDot = className.lastIndexOf('.');
+ String packageName = className;
+ if (lastDot != -1) packageName = className.substring(0, lastDot);
+ security.checkPackageAccess(packageName);
+ }
+ Class providerClass;
+ if (cl == null) {
+ // XXX Use the bootstrap ClassLoader. There is no way to
+ // load a class using the bootstrap ClassLoader that works
+ // in both JDK 1.1 and Java 2. However, this should still
+ // work b/c the following should be true:
+ //
+ // (cl == null) iff current ClassLoader == null
+ //
+ // Thus Class.forName(String) will use the current
+ // ClassLoader which will be the bootstrap ClassLoader.
+ providerClass = Class.forName(className);
+ } else {
+ try {
+ providerClass = cl.loadClass(className);
+ } catch (ClassNotFoundException x) {
+ if (doFallback) {
+ // Fall back to current classloader
+ ClassLoader current = ObjectFactory.class.getClassLoader();
+ if (current == null) {
+ providerClass = Class.forName(className);
+ } else if (cl != current) {
+ cl = current;
+ providerClass = cl.loadClass(className);
+ } else {
+ throw x;
+ }
+ } else {
+ throw x;
+ }
+ }
+ }
+
+ return providerClass;
+ }
+
+ /*
+ * Try to find provider using Jar Service Provider Mechanism
+ *
+ * @return instance of provider class if found or null
+ */
+ private static Object findJarServiceProvider(String factoryId)
+ throws ConfigurationError
+ {
+ String serviceId = "META-INF/services/" + factoryId;
+ InputStream is = null;
+
+ // First try the Context ClassLoader
+ ClassLoader cl = findClassLoader();
+
+ is = SecuritySupport.getResourceAsStream(cl, serviceId);
+
+ // If no provider found then try the current ClassLoader
+ if (is == null) {
+ ClassLoader current = ObjectFactory.class.getClassLoader();
+ if (cl != current) {
+ cl = current;
+ is = SecuritySupport.getResourceAsStream(cl, serviceId);
+ }
+ }
+
+ if (is == null) {
+ // No provider found
+ return null;
+ }
+
+ if (DEBUG) debugPrintln("found jar resource=" + serviceId +
+ " using ClassLoader: " + cl);
+
+ // Read the service provider name in UTF-8 as specified in
+ // the jar spec. Unfortunately this fails in Microsoft
+ // VJ++, which does not implement the UTF-8
+ // encoding. Theoretically, we should simply let it fail in
+ // that case, since the JVM is obviously broken if it
+ // doesn't support such a basic standard. But since there
+ // are still some users attempting to use VJ++ for
+ // development, we have dropped in a fallback which makes a
+ // second attempt using the platform's default encoding. In
+ // VJ++ this is apparently ASCII, which is a subset of
+ // UTF-8... and since the strings we'll be reading here are
+ // also primarily limited to the 7-bit ASCII range (at
+ // least, in English versions), this should work well
+ // enough to keep us on the air until we're ready to
+ // officially decommit from VJ++. [Edited comment from
+ // jkesselm]
+ BufferedReader rd;
+ try {
+ rd = new BufferedReader(new InputStreamReader(is, "UTF-8"), DEFAULT_LINE_LENGTH);
+ } catch (java.io.UnsupportedEncodingException e) {
+ rd = new BufferedReader(new InputStreamReader(is), DEFAULT_LINE_LENGTH);
+ }
+
+ String factoryClassName = null;
+ try {
+ // XXX Does not handle all possible input as specified by the
+ // Jar Service Provider specification
+ factoryClassName = rd.readLine();
+ } catch (IOException x) {
+ // No provider found
+ return null;
+ }
+ finally {
+ try {
+ // try to close the reader.
+ rd.close();
+ }
+ // Ignore the exception.
+ catch (IOException exc) {}
+ }
+
+ if (factoryClassName != null &&
+ ! "".equals(factoryClassName)) {
+ if (DEBUG) debugPrintln("found in resource, value="
+ + factoryClassName);
+
+ // Note: here we do not want to fall back to the current
+ // ClassLoader because we want to avoid the case where the
+ // resource file was found using one ClassLoader and the
+ // provider class was instantiated using a different one.
+ return newInstance(factoryClassName, cl, false);
+ }
+
+ // No provider found
+ return null;
+ }
+
+ //
+ // Classes
+ //
+
+ /**
+ * A configuration error.
+ */
+ static final class ConfigurationError
+ extends Error {
+
+ /** Serialization version. */
+ static final long serialVersionUID = 2646822752226280048L;
+
+ //
+ // Data
+ //
+
+ /** Exception. */
+ private Exception exception;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Construct a new instance with the specified detail string and
+ * exception.
+ */
+ ConfigurationError(String msg, Exception x) {
+ super(msg);
+ this.exception = x;
+ } // (String,Exception)
+
+ //
+ // methods
+ //
+
+ /** Returns the exception associated to this error. */
+ Exception getException() {
+ return exception;
+ } // getException():Exception
+
+ } // class ConfigurationError
+
+} // class ObjectFactory
diff --git a/resources/xerces2-j-src/org/apache/html/dom/SecuritySupport.java b/resources/xerces2-j-src/org/apache/html/dom/SecuritySupport.java
new file mode 100644
index 0000000..07bdfce
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/html/dom/SecuritySupport.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.html.dom;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * This class is duplicated for each subpackage so keep it in sync.
+ * It is package private and therefore is not exposed as part of any API.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+final class SecuritySupport {
+
+ static ClassLoader getContextClassLoader() {
+ return (ClassLoader)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ ClassLoader cl = null;
+ try {
+ cl = Thread.currentThread().getContextClassLoader();
+ } catch (SecurityException ex) { }
+ return cl;
+ }
+ });
+ }
+
+ static ClassLoader getSystemClassLoader() {
+ return (ClassLoader)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ ClassLoader cl = null;
+ try {
+ cl = ClassLoader.getSystemClassLoader();
+ } catch (SecurityException ex) {}
+ return cl;
+ }
+ });
+ }
+
+ static ClassLoader getParentClassLoader(final ClassLoader cl) {
+ return (ClassLoader)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ ClassLoader parent = null;
+ try {
+ parent = cl.getParent();
+ } catch (SecurityException ex) {}
+
+ // eliminate loops in case of the boot
+ // ClassLoader returning itself as a parent
+ return (parent == cl) ? null : parent;
+ }
+ });
+ }
+
+ static String getSystemProperty(final String propName) {
+ return (String)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return System.getProperty(propName);
+ }
+ });
+ }
+
+ static FileInputStream getFileInputStream(final File file)
+ throws FileNotFoundException
+ {
+ try {
+ return (FileInputStream)
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws FileNotFoundException {
+ return new FileInputStream(file);
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw (FileNotFoundException)e.getException();
+ }
+ }
+
+ static InputStream getResourceAsStream(final ClassLoader cl,
+ final String name)
+ {
+ return (InputStream)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ InputStream ris;
+ if (cl == null) {
+ ris = ClassLoader.getSystemResourceAsStream(name);
+ } else {
+ ris = cl.getResourceAsStream(name);
+ }
+ return ris;
+ }
+ });
+ }
+
+ static boolean getFileExists(final File f) {
+ return ((Boolean)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return f.exists() ? Boolean.TRUE : Boolean.FALSE;
+ }
+ })).booleanValue();
+ }
+
+ static long getLastModified(final File f) {
+ return ((Long)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return new Long(f.lastModified());
+ }
+ })).longValue();
+ }
+
+ private SecuritySupport () {}
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLAElement.java b/resources/xerces2-j-src/org/apache/wml/WMLAElement.java
new file mode 100644
index 0000000..bbb20f7
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLAElement.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLAElement extends WMLElement {
+
+ public void setHref(String newValue);
+ public String getHref();
+
+ public void setTitle(String newValue);
+ public String getTitle();
+
+ public void setId(String newValue);
+ public String getId();
+
+ /**
+ * 'xml:lang' specifics the natural or formal language in which
+ * the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLAccessElement.java b/resources/xerces2-j-src/org/apache/wml/WMLAccessElement.java
new file mode 100644
index 0000000..6c39c20
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLAccessElement.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'access' element specifics the access control for the entire deck
+ * (Section 11.3.1, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLAccessElement extends WMLElement {
+
+ /**
+ * A deck's domain and path attributes specify which deck may
+ * access it.
+ *
+ * domain attribute is suffix-matched against the domain name
+ * portion of the referring URI
+ */
+ public void setDomain(String newValue);
+ public String getDomain();
+
+ /**
+ * path attribute is prefix-matched against the path portion of
+ * the referring URI
+ */
+ public void setPath(String newValue);
+ public String getPath();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLAnchorElement.java b/resources/xerces2-j-src/org/apache/wml/WMLAnchorElement.java
new file mode 100644
index 0000000..8f8e31d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLAnchorElement.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLAnchorElement extends WMLElement {
+
+ public void setTitle(String newValue);
+ public String getTitle();
+
+ /**
+ * 'xml:lang' specifics the natural or formal language in which
+ * the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLBElement.java b/resources/xerces2-j-src/org/apache/wml/WMLBElement.java
new file mode 100644
index 0000000..5e67174
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLBElement.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'b' element boldface the text
+ * (Section 11.8.1, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLBElement extends WMLElement {
+ /**
+ * 'xml:lang' specifics the natural or formal language in which
+ * the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLBigElement.java b/resources/xerces2-j-src/org/apache/wml/WMLBigElement.java
new file mode 100644
index 0000000..28a96af
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLBigElement.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'big' element renders the text with big font
+ * (Section 11.8.1, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLBigElement extends WMLElement {
+ /**
+ * 'xml:lang' specifics the natural or formal language in which
+ * the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLBrElement.java b/resources/xerces2-j-src/org/apache/wml/WMLBrElement.java
new file mode 100644
index 0000000..adb6af5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLBrElement.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'br' element starts a new line
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLBrElement extends WMLElement {
+ /**
+ * 'xml:lang' specifics the natural or formal language in which
+ * the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLCardElement.java b/resources/xerces2-j-src/org/apache/wml/WMLCardElement.java
new file mode 100644
index 0000000..de15b9a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLCardElement.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'card' element is the basic display unit of WML. A WML decks
+ * contains a collection of cards.
+ * (Section 11.5, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLCardElement extends WMLElement {
+
+ /**
+ * 'onenterbackward' specifies the event to occur when a user
+ * agent into a card using a 'go' task
+ * (Section 11.5.1, WAP WML Version 16-Jun-1999)
+ */
+ public void setOnEnterBackward(String href);
+ public String getOnEnterBackward();
+
+ /**
+ * 'onenterforward' specifies the event to occur when a user
+ * agent into a card using a 'prev' task
+ * (Section 11.5.1, WAP WML Version 16-Jun-1999)
+ */
+ public void setOnEnterForward(String href);
+ public String getOnEnterForward();
+
+ /**
+ * 'onenterbackward' specifies the event to occur when a timer expires
+ * (Section 11.5.1, WAP WML Version 16-Jun-1999)
+ */
+ public void setOnTimer(String href);
+ public String getOnTimer();
+
+ /**
+ * 'title' specifies a advisory info about the card
+ * (Section 11.5.2, WAP WML Version 16-Jun-1999)
+ */
+ public void setTitle(String newValue);
+ public String getTitle();
+
+ /**
+ * 'newcontext' specifies whether a browser context should be
+ * re-initialized upon entering the card. Default to be false.
+ * (Section 11.5.2, WAP WML Version 16-Jun-1999)
+ */
+ public void setNewContext(boolean newValue);
+ public boolean getNewContext();
+
+ /**
+ * 'ordered' attribute specifies a hit to user agent about the
+ * organization of the card's content
+ * (Section 11.5.2, WAP WML Version 16-Jun-1999)
+ */
+ public void setOrdered(boolean newValue);
+ public boolean getOrdered();
+
+ /**
+ * 'xml:lang' specifics the natural or formal language in which
+ * the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLDOMImplementation.java b/resources/xerces2-j-src/org/apache/wml/WMLDOMImplementation.java
new file mode 100644
index 0000000..07517e5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLDOMImplementation.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+import org.w3c.dom.DOMImplementation;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * @version $Id$
+ * @author David Li
+ */
+public interface WMLDOMImplementation extends DOMImplementation {
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLDoElement.java b/resources/xerces2-j-src/org/apache/wml/WMLDoElement.java
new file mode 100644
index 0000000..a1cb03a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLDoElement.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLDoElement extends WMLElement {
+
+ public void setOptional(String newValue);
+ public String getOptional();
+
+ public void setLabel(String newValue);
+ public String getLabel();
+
+ public void setType(String newValue);
+ public String getType();
+
+ public void setName(String newValue);
+ public String getName();
+
+ /**
+ * The xml:lang that specifics the natural or formal language in
+ * which the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLDocument.java b/resources/xerces2-j-src/org/apache/wml/WMLDocument.java
new file mode 100644
index 0000000..b09b59d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLDocument.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+import org.w3c.dom.Document;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLDocument extends Document {
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLElement.java b/resources/xerces2-j-src/org/apache/wml/WMLElement.java
new file mode 100644
index 0000000..20da15a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLElement.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+import org.w3c.dom.Element;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * All WML Elements are derived from this class that contains two
+ * core attributes defined in the DTD.
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLElement extends Element {
+
+ /**
+ * The element's identifier which is unique in a single deck.
+ * (Section 8.9, WAP WML Version 16-Jun-1999)
+ */
+ public void setId(String newValue);
+ public String getId();
+
+ /**
+ * The 'class' attribute of a element that affiliates an elements
+ * with one or more elements.
+ * (Section 8.9, WAP WML Version 16-Jun-1999)
+ */
+ public void setClassName(String newValue);
+ public String getClassName();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLEmElement.java b/resources/xerces2-j-src/org/apache/wml/WMLEmElement.java
new file mode 100644
index 0000000..3f93825
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLEmElement.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'em' element emphasis the text
+ * (Section 11.8.1, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLEmElement extends WMLElement {
+ /**
+ * The xml:lang that specifics the natural or formal language in
+ * which the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLFieldsetElement.java b/resources/xerces2-j-src/org/apache/wml/WMLFieldsetElement.java
new file mode 100644
index 0000000..34e7338
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLFieldsetElement.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'fieldset' element groups related fields and tet
+ * (Section 11.6.4, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+public interface WMLFieldsetElement extends WMLElement {
+
+ /**
+ * 'title' specifies a title for this element
+ */
+ public void setTitle(String newValue);
+ public String getTitle();
+
+ /**
+ * The xml:lang that specifics the natural or formal language in
+ * which the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLGoElement.java b/resources/xerces2-j-src/org/apache/wml/WMLGoElement.java
new file mode 100644
index 0000000..2f7e791
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLGoElement.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLGoElement extends WMLElement {
+
+ public void setSendreferer(String newValue);
+
+ public String getSendreferer();
+
+ public void setAcceptCharset(String newValue);
+
+ public String getAcceptCharset();
+
+ public void setHref(String newValue);
+
+ public String getHref();
+
+ public void setMethod(String newValue);
+
+ public String getMethod();
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLHeadElement.java b/resources/xerces2-j-src/org/apache/wml/WMLHeadElement.java
new file mode 100644
index 0000000..e197e60
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLHeadElement.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * The head element contains information about a deck.
+ * (Section 11.3, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLHeadElement extends WMLElement {
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLIElement.java b/resources/xerces2-j-src/org/apache/wml/WMLIElement.java
new file mode 100644
index 0000000..9ecc546
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLIElement.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'i' italic the text
+ * (Section 11.8.1, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLIElement extends WMLElement {
+ /**
+ * The xml:lang that specifics the natural or formal language in
+ * which the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLImgElement.java b/resources/xerces2-j-src/org/apache/wml/WMLImgElement.java
new file mode 100644
index 0000000..b8abb1f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLImgElement.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'img' specifies an image in a text flow
+ * (Section 11.9, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+public interface WMLImgElement extends WMLElement {
+
+ /**
+ * 'alt' specifies an alternative text for the image
+ * (Section 11.9, WAP WML Version 16-Jun-1999)
+ */
+ public void setAlt(String newValue);
+ public String getAlt();
+
+ /**
+ * 'src' specifies URI for the source images
+ * (Section 11.9, WAP WML Version 16-Jun-1999)
+ */
+ public void setSrc(String newValue);
+ public String getSrc();
+
+ /**
+ * 'localsrc' specifies an alternative internal representation of
+ * the image.
+ * (Section 11.9, WAP WML Version 16-Jun-1999)
+ */
+ public void setLocalSrc(String newValue);
+ public String getLocalSrc();
+
+ /**
+ * 'vspace' specifies the abount of white space to be inserted
+ * above and below
+ * (Section 11.9, WAP WML Version 16-Jun-1999)
+ */
+ public void setVspace(String newValue);
+ public String getVspace();
+
+ /**
+ * 'hspace' specifies the abount of white space to be inserted
+ * left and right
+ * (Section 11.9, WAP WML Version 16-Jun-1999)
+ */
+ public void setHspace(String newValue);
+ public String getHspace();
+
+ /**
+ * 'align' specifies the alignment of the image within the text
+ * flow.
+ * (Section 11.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setAlign(String newValue);
+ public String getAlign();
+
+ /**
+ * 'width' specifies the width of an image.
+ * (Section 11.9, WAP WML Version 16-Jun-1999)
+ */
+ public void setWidth(String newValue);
+ public String getWidth();
+
+ /**
+ * 'height' specifies the height of an image.
+ * (Section 11.9, WAP WML Version 16-Jun-1999)
+ */
+ public void setHeight(String newValue);
+ public String getHeight();
+
+ /**
+ * The xml:lang that specifics the natural or formal language in
+ * which the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLInputElement.java b/resources/xerces2-j-src/org/apache/wml/WMLInputElement.java
new file mode 100644
index 0000000..33c21cc
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLInputElement.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'input' element specifies a text entry object.
+ * (Section 11.6.3, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLInputElement extends WMLElement {
+
+ /**
+ * 'name' specifies the name of a variable after the user enters the text.
+ * (Section 11.6.3, WAP WML Version 16-Jun-1999)
+ */
+ public void setName(String newValue);
+ public String getName();
+
+ /**
+ * 'value' specifies the default value of the variable in 'name' attribute
+ * (Section 11.6.3, WAP WML Version 16-Jun-1999)
+ */
+ public void setValue(String newValue);
+ public String getValue();
+
+ /**
+ * 'type' specifies the type of text input area.
+ * Two values are allowed: 'text' and 'password' and default is 'text'
+ * (Section 11.6.3, WAP WML Version 16-Jun-1999)
+ */
+ public void setType(String newValue);
+ public String getType();
+
+ /**
+ * 'format' specifies the input mask for user input.
+ * (Section 11.6.3, WAP WML Version 16-Jun-1999)
+ */
+ public void setFormat(String newValue);
+ public String getFormat();
+
+ /**
+ * 'emptyok' specifies whether a empty input is allowed when a
+ * non-empty 'format' is specified. Default to be 'false'
+ * (Section 11.6.3, WAP WML Version 16-Jun-1999)
+ */
+ public void setEmptyOk(boolean newValue);
+ public boolean getEmptyOk();
+
+ /**
+ * 'size' specifies the width of the input in characters
+ * (Section 11.6.3, WAP WML Version 16-Jun-1999)
+ */
+ public void setSize(int newValue);
+ public int getSize();
+
+ /**
+ * 'maxlength' specifies the maximum number of characters to be
+ * enter.
+ * (Section 11.6.3, WAP WML Version 16-Jun-1999)
+ */
+ public void setMaxLength(int newValue);
+ public int getMaxLength();
+
+ /**
+ * 'title' specifies a title for this element
+ * (Section 11.6.3, WAP WML Version 16-Jun-1999)
+ */
+ public void setTitle(String newValue);
+ public String getTitle();
+
+ /**
+ * 'tabindex' specifies the tabbing position of the element
+ * (Section 11.6.1, WAP WML Version 16-Jun-1999)
+ */
+ public void setTabIndex(int newValue);
+ public int getTabIndex();
+
+ /**
+ * 'xml:lang' specifics the natural or formal language in which
+ * the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLMetaElement.java b/resources/xerces2-j-src/org/apache/wml/WMLMetaElement.java
new file mode 100644
index 0000000..71224ee
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLMetaElement.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * The meta element contains meta-info of an WML deck
+ * (Section 11.3.2, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+public interface WMLMetaElement extends WMLElement {
+
+ /**
+ * 'name' attribute specific the property name
+ */
+ public void setName(String newValue);
+ public String getName();
+
+ /**
+ * 'http-equiv' attribute indicates the property should be
+ * interpret as HTTP header.
+ */
+ public void setHttpEquiv(String newValue);
+ public String getHttpEquiv();
+
+ /**
+ * 'forua' attribute specifies whether a intermediate agent should
+ * remove this meta element. A value of false means the
+ * intermediate agent must remove the element.
+ */
+ public void setForua(boolean newValue);
+ public boolean getForua();
+
+ /**
+ * 'scheme' attribute specifies a form that may be used to
+ * interpret the property value
+ */
+ public void setScheme(String newValue);
+ public String getScheme();
+
+ /**
+ * 'content' attribute specifies the property value
+ */
+ public void setContent(String newValue);
+ public String getContent();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLNoopElement.java b/resources/xerces2-j-src/org/apache/wml/WMLNoopElement.java
new file mode 100644
index 0000000..be77756
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLNoopElement.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * @version $Id$
+ * @author David Li
+ */
+public interface WMLNoopElement extends WMLElement {
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLOneventElement.java b/resources/xerces2-j-src/org/apache/wml/WMLOneventElement.java
new file mode 100644
index 0000000..06ed515
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLOneventElement.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLOneventElement extends WMLElement {
+
+ public void setType(String newValue);
+
+ public String getType();
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLOptgroupElement.java b/resources/xerces2-j-src/org/apache/wml/WMLOptgroupElement.java
new file mode 100644
index 0000000..02e16e4
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLOptgroupElement.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'optgroup' element groups related 'option' elements into a
+ * hierarchy. (Section 11.6.2.2, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLOptgroupElement extends WMLElement {
+
+ /**
+ * 'title' specifies the title of this element
+ * (Section 11.6.2.3, WAP WML Version 16-Jun-1999)
+ */
+ public void setTitle(String newValue);
+ public String getTitle();
+
+ /**
+ * 'xml:lang' specifics the natural or formal language in which
+ * the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLOptionElement.java b/resources/xerces2-j-src/org/apache/wml/WMLOptionElement.java
new file mode 100644
index 0000000..943a860
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLOptionElement.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'option' element specifies a choice in a 'select' element
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLOptionElement extends WMLElement {
+
+ /**
+ * 'value' specifies the value to used to set the 'name' variable
+ * (Section 11.6.2.2, WAP WML Version 16-Jun-1999)
+ */
+ public void setValue(String newValue);
+ public String getValue();
+
+ /**
+ * 'title' specifies a title for this element.
+ * (Section 11.6.2.2, WAP WML Version 16-Jun-1999)
+ */
+ public void setTitle(String newValue);
+ public String getTitle();
+
+ /**
+ * 'onpick' specifies a event to occur when a user select and
+ * disselect this choice.
+ * (Section 11.6.2.2, WAP WML Version 16-Jun-1999) */
+ public void setOnPick(String href);
+ public String getOnPick();
+
+ /**
+ * 'xml:lang' specifics the natural or formal language in which
+ * the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLPElement.java b/resources/xerces2-j-src/org/apache/wml/WMLPElement.java
new file mode 100644
index 0000000..f8f6b0d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLPElement.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'p' element specifies a paragraph
+ * (Section 11.8.3, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLPElement extends WMLElement {
+
+ /**
+ * 'mode' specifies the wrapping mode of the paragraph.
+ * The legal values are 'wrap' and 'nowrap'
+ * (Section 11.8.3, WAP WML Version 16-Jun-1999)
+ */
+ public void setMode(String newValue);
+ public String getMode();
+
+ /**
+ * 'align' specifies the align of teh paragraph
+ * The legal values are 'left,' 'center,' and 'right'
+ * (Section 11.8.3, WAP WML Version 16-Jun-1999)
+ */
+ public void setAlign(String newValue);
+ public String getAlign();
+
+ /**
+ * The xml:lang that specifics the natural or formal language in
+ * which the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLPostfieldElement.java b/resources/xerces2-j-src/org/apache/wml/WMLPostfieldElement.java
new file mode 100644
index 0000000..f6de42c
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLPostfieldElement.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLPostfieldElement extends WMLElement {
+
+ public void setValue(String newValue);
+
+ public String getValue();
+
+ public void setName(String newValue);
+
+ public String getName();
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLPrevElement.java b/resources/xerces2-j-src/org/apache/wml/WMLPrevElement.java
new file mode 100644
index 0000000..c9a38a5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLPrevElement.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLPrevElement extends WMLElement {
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLRefreshElement.java b/resources/xerces2-j-src/org/apache/wml/WMLRefreshElement.java
new file mode 100644
index 0000000..74d9a8e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLRefreshElement.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLRefreshElement extends WMLElement {
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLSelectElement.java b/resources/xerces2-j-src/org/apache/wml/WMLSelectElement.java
new file mode 100644
index 0000000..68cf57d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLSelectElement.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'select' element lets user pick from a list of options.
+ * (Section 11.6.2.1, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+public interface WMLSelectElement extends WMLElement {
+
+ /**
+ * 'tabindex' specifies the tabbing position of the element
+ * (Section 11.6.1, WAP WML Version 16-Jun-1999)
+ */
+ public void setTabIndex(int newValue);
+ public int getTabIndex();
+
+ /**
+ * 'multiple' indicates whether a list accept multiple selection
+ * (Section 11.6.2.1, WAP WML Version 16-Jun-1999)
+ */
+ public void setMultiple(boolean newValue);
+ public boolean getMultiple();
+
+ /**
+ * 'name' specifies the name of variable to be set.
+ * (Section 11.6.2.1, WAP WML Version 16-Jun-1999)
+ */
+ public void setName(String newValue);
+ public String getName();
+
+ /**
+ * 'value' specifics the default value of the variable of 'name'
+ * (Section 11.6.2.1, WAP WML Version 16-Jun-1999)
+ */
+ public void setValue(String newValue);
+ public String getValue();
+
+ /**
+ * 'title' specifies a title for this element
+ * (Section 11.6.2.1, WAP WML Version 16-Jun-1999)
+ */
+ public void setTitle(String newValue);
+ public String getTitle();
+
+ /**
+ * 'iname' specifies name of variable to be set with the index
+ * result of selection.
+ * (Section 11.6.2.1, WAP WML Version 16-Jun-1999)
+ */
+ public void setIName(String newValue);
+ public String getIName();
+
+ /**
+ * 'ivalue' specifies the default of the variable 'iname'
+ */
+ public void setIValue(String newValue);
+ public String getIValue();
+
+ /**
+ * 'xml:lang' specifics the natural or formal language in which
+ * the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLSetvarElement.java b/resources/xerces2-j-src/org/apache/wml/WMLSetvarElement.java
new file mode 100644
index 0000000..87600b1
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLSetvarElement.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLSetvarElement extends WMLElement {
+
+ public void setValue(String newValue);
+
+ public String getValue();
+
+ public void setName(String newValue);
+
+ public String getName();
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLSmallElement.java b/resources/xerces2-j-src/org/apache/wml/WMLSmallElement.java
new file mode 100644
index 0000000..aece9ba
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLSmallElement.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'small' render the text with small font
+ * (Section 11.8.1, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+public interface WMLSmallElement extends WMLElement {
+ /**
+ * The xml:lang that specifics the natural or formal language in
+ * which the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLStrongElement.java b/resources/xerces2-j-src/org/apache/wml/WMLStrongElement.java
new file mode 100644
index 0000000..9434bbf
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLStrongElement.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'strong' strongly emphasis the text
+ * (Section 11.8.1, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLStrongElement extends WMLElement {
+ /**
+ * The xml:lang that specifics the natural or formal language in
+ * which the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLTableElement.java b/resources/xerces2-j-src/org/apache/wml/WMLTableElement.java
new file mode 100644
index 0000000..f1e8605
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLTableElement.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'table' create a set of aligned columns of text and images.
+ * (Section 11.8.5, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLTableElement extends WMLElement {
+
+ /**
+ * 'title' specifies a title for the table
+ * (Section 11.8.5, WAP WML Version 16-Jun-1999)
+ */
+ public void setTitle(String newValue);
+ public String getTitle();
+
+ /**
+ * 'align' set the align of the table
+ * (Section 11.8.5, WAP WML Version 16-Jun-1999)
+ */
+ public void setAlign(String newValue);
+ public String getAlign();
+
+ /**
+ * 'columns' specifies the number of columns
+ * (Section 11.8.5, WAP WML Version 16-Jun-1999)
+ */
+ public void setColumns(int newValue);
+ public int getColumns();
+
+ /**
+ * The xml:lang that specifics the natural or formal language in
+ * which the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLTdElement.java b/resources/xerces2-j-src/org/apache/wml/WMLTdElement.java
new file mode 100644
index 0000000..27b91ca
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLTdElement.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'td' specifies a single table cell with in a row
+ * (Section 11.8.6, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLTdElement extends WMLElement {
+ /**
+ * The xml:lang that specifics the natural or formal language in
+ * which the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLTemplateElement.java b/resources/xerces2-j-src/org/apache/wml/WMLTemplateElement.java
new file mode 100644
index 0000000..15f9af0
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLTemplateElement.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * The 'template' element declares a template for the cards in the deck.
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLTemplateElement extends WMLElement {
+
+ public void setOnTimer(String newValue);
+ public String getOnTimer();
+
+ public void setOnEnterBackward(String newValue);
+ public String getOnEnterBackward();
+
+ public void setOnEnterForward(String newValue);
+ public String getOnEnterForward();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLTimerElement.java b/resources/xerces2-j-src/org/apache/wml/WMLTimerElement.java
new file mode 100644
index 0000000..00efdee
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLTimerElement.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'timer' elements declares a card timer.
+ * (Section 11.6.7, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLTimerElement extends WMLElement {
+ /**
+ * 'name' specifies the name of variable ot be set with the value
+ * of the timer.
+ * (Section 11.6.7, WAP WML Version 16-Jun-1999)
+ */
+ public void setName(String newValue);
+ public String getName();
+
+ /**
+ * 'value' indicates teh default of the variable 'name'
+ * (Section 11.6.7, WAP WML Version 16-Jun-1999)
+ */
+ public void setValue(String newValue);
+ public String getValue();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLTrElement.java b/resources/xerces2-j-src/org/apache/wml/WMLTrElement.java
new file mode 100644
index 0000000..bad2e7e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLTrElement.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'tr' specifies a single row
+ * (Section 11.8.6, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLTrElement extends WMLElement {
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLUElement.java b/resources/xerces2-j-src/org/apache/wml/WMLUElement.java
new file mode 100644
index 0000000..89d71f9
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLUElement.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'u' underline the text
+ * (Section 11.8.1, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLUElement extends WMLElement {
+ /**
+ * The xml:lang that specifics the natural or formal language in
+ * which the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/WMLWmlElement.java b/resources/xerces2-j-src/org/apache/wml/WMLWmlElement.java
new file mode 100644
index 0000000..8fab453
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/WMLWmlElement.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml;
+
+/**
+ * The interface is modeled after DOM1 Spec for HTML from W3C.
+ * The DTD used in this DOM model is from
+ *
+ * http://www.wapforum.org/DTD/wml_1.1.xml
+ *
+ * 'wml' is the root oot of a WML document.
+ * (Section 11.2, WAP WML Version 16-Jun-1999)
+ *
+ * @version $Id$
+ * @author David Li
+ */
+
+public interface WMLWmlElement extends WMLElement {
+ /**
+ * The xml:lang that specifics the natural or formal language in
+ * which the document is written.
+ * (Section 8.8, WAP WML Version 16-Jun-1999)
+ */
+ public void setXmlLang(String newValue);
+ public String getXmlLang();
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLAElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLAElementImpl.java
new file mode 100644
index 0000000..70be9c8
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLAElementImpl.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLAElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLAElementImpl extends WMLElementImpl implements WMLAElement {
+
+ private static final long serialVersionUID = 2628169803370301255L;
+
+ public WMLAElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setHref(String newValue) {
+ setAttribute("href", newValue);
+ }
+
+ public String getHref() {
+ return getAttribute("href");
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setTitle(String newValue) {
+ setAttribute("title", newValue);
+ }
+
+ public String getTitle() {
+ return getAttribute("title");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLAccessElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLAccessElementImpl.java
new file mode 100644
index 0000000..48dab9c
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLAccessElementImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLAccessElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLAccessElementImpl extends WMLElementImpl implements WMLAccessElement {
+
+ private static final long serialVersionUID = -235627181817012806L;
+
+ public WMLAccessElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setDomain(String newValue) {
+ setAttribute("domain", newValue);
+ }
+
+ public String getDomain() {
+ return getAttribute("domain");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setPath(String newValue) {
+ setAttribute("path", newValue);
+ }
+
+ public String getPath() {
+ return getAttribute("path");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLAnchorElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLAnchorElementImpl.java
new file mode 100644
index 0000000..7a71bf4
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLAnchorElementImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLAnchorElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLAnchorElementImpl extends WMLElementImpl implements WMLAnchorElement {
+
+ private static final long serialVersionUID = 5720492496046133176L;
+
+ public WMLAnchorElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setTitle(String newValue) {
+ setAttribute("title", newValue);
+ }
+
+ public String getTitle() {
+ return getAttribute("title");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLBElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLBElementImpl.java
new file mode 100644
index 0000000..fbac978
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLBElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLBElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLBElementImpl extends WMLElementImpl implements WMLBElement {
+
+ private static final long serialVersionUID = -758504371498228671L;
+
+ public WMLBElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLBigElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLBigElementImpl.java
new file mode 100644
index 0000000..bf51756
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLBigElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLBigElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLBigElementImpl extends WMLElementImpl implements WMLBigElement {
+
+ private static final long serialVersionUID = -8826061369691668904L;
+
+ public WMLBigElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLBrElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLBrElementImpl.java
new file mode 100644
index 0000000..9ef2345
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLBrElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLBrElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLBrElementImpl extends WMLElementImpl implements WMLBrElement {
+
+ private static final long serialVersionUID = -5047802409550691268L;
+
+ public WMLBrElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLCardElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLCardElementImpl.java
new file mode 100644
index 0000000..efbb53e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLCardElementImpl.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLCardElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLCardElementImpl extends WMLElementImpl implements WMLCardElement {
+
+ private static final long serialVersionUID = -3571126568344328924L;
+
+ public WMLCardElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setOnTimer(String newValue) {
+ setAttribute("ontimer", newValue);
+ }
+
+ public String getOnTimer() {
+ return getAttribute("ontimer");
+ }
+
+ public void setOrdered(boolean newValue) {
+ setAttribute("ordered", newValue);
+ }
+
+ public boolean getOrdered() {
+ return getAttribute("ordered", true);
+ }
+
+ public void setOnEnterBackward(String newValue) {
+ setAttribute("onenterbackward", newValue);
+ }
+
+ public String getOnEnterBackward() {
+ return getAttribute("onenterbackward");
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setTitle(String newValue) {
+ setAttribute("title", newValue);
+ }
+
+ public String getTitle() {
+ return getAttribute("title");
+ }
+
+ public void setNewContext(boolean newValue) {
+ setAttribute("newcontext", newValue);
+ }
+
+ public boolean getNewContext() {
+ return getAttribute("newcontext", false);
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setOnEnterForward(String newValue) {
+ setAttribute("onenterforward", newValue);
+ }
+
+ public String getOnEnterForward() {
+ return getAttribute("onenterforward");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLDOMImplementationImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLDOMImplementationImpl.java
new file mode 100644
index 0000000..be5b4d6
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLDOMImplementationImpl.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLDOMImplementation;
+import org.apache.xerces.dom.CoreDocumentImpl;
+import org.apache.xerces.dom.DOMImplementationImpl;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.DocumentType;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLDOMImplementationImpl extends DOMImplementationImpl implements WMLDOMImplementation {
+
+ static final DOMImplementationImpl singleton = new WMLDOMImplementationImpl();
+
+ /** NON-DOM: Obtain and return the single shared object */
+ public static DOMImplementation getDOMImplementation() {
+ return singleton;
+ }
+
+ //
+ // Protected methods
+ //
+
+ protected CoreDocumentImpl createDocument(DocumentType doctype) {
+ return new WMLDocumentImpl(doctype);
+ }
+}
+
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLDoElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLDoElementImpl.java
new file mode 100644
index 0000000..68fe14a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLDoElementImpl.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLDoElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLDoElementImpl extends WMLElementImpl implements WMLDoElement {
+
+ private static final long serialVersionUID = 7755861458464251322L;
+
+ public WMLDoElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setOptional(String newValue) {
+ setAttribute("optional", newValue);
+ }
+
+ public String getOptional() {
+ return getAttribute("optional");
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setLabel(String newValue) {
+ setAttribute("label", newValue);
+ }
+
+ public String getLabel() {
+ return getAttribute("label");
+ }
+
+ public void setType(String newValue) {
+ setAttribute("type", newValue);
+ }
+
+ public String getType() {
+ return getAttribute("type");
+ }
+
+ public void setName(String newValue) {
+ setAttribute("name", newValue);
+ }
+
+ public String getName() {
+ return getAttribute("name");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLDocumentImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLDocumentImpl.java
new file mode 100644
index 0000000..ffadafe
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLDocumentImpl.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import java.lang.reflect.Constructor;
+import java.util.Hashtable;
+
+import org.apache.wml.WMLDocument;
+import org.apache.xerces.dom.DocumentImpl;
+import org.apache.xerces.dom.ElementImpl;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLDocumentImpl extends DocumentImpl implements WMLDocument {
+
+ private static final long serialVersionUID = -6582904849512384104L;
+
+ private static Hashtable _elementTypesWML;
+ private static final Class[] _elemClassSigWML =
+ new Class[] { WMLDocumentImpl.class, String.class };
+
+ public Element createElement( String tagName ) throws DOMException
+ {
+ Class elemClass;
+ Constructor cnst;
+
+ elemClass = (Class) _elementTypesWML.get( tagName );
+ if ( elemClass != null ) {
+ try {
+ cnst = elemClass.getConstructor( _elemClassSigWML );
+ return (Element) cnst.newInstance( new Object[] { this, tagName } );
+ } catch ( Exception except ) {
+ Throwable thrw;
+
+ if ( except instanceof java.lang.reflect.InvocationTargetException )
+ thrw = ( (java.lang.reflect.InvocationTargetException) except ).getTargetException();
+ else
+ thrw = except;
+
+ System.out.println( "Exception " + thrw.getClass().getName() );
+ System.out.println( thrw.getMessage() );
+
+ throw new IllegalStateException( "Tag '" + tagName + "' associated with an Element class that failed to construct." );
+ }
+ }
+ return new WMLElementImpl( this, tagName );
+ }
+
+ /* (non-Javadoc)
+ * @see CoreDocumentImpl#canRenameElements()
+ */
+ protected boolean canRenameElements(String newNamespaceURI, String newNodeName, ElementImpl el) {
+ // check whether a class change is required
+ return _elementTypesWML.get(newNodeName) == _elementTypesWML.get(el.getTagName());
+ }
+
+ static {
+ _elementTypesWML = new Hashtable();
+ _elementTypesWML.put("b", WMLBElementImpl.class);
+ _elementTypesWML.put("noop", WMLNoopElementImpl.class);
+ _elementTypesWML.put("a", WMLAElementImpl.class);
+ _elementTypesWML.put("setvar", WMLSetvarElementImpl.class);
+ _elementTypesWML.put("access", WMLAccessElementImpl.class);
+ _elementTypesWML.put("strong", WMLStrongElementImpl.class);
+ _elementTypesWML.put("postfield", WMLPostfieldElementImpl.class);
+ _elementTypesWML.put("do", WMLDoElementImpl.class);
+ _elementTypesWML.put("wml", WMLWmlElementImpl.class);
+ _elementTypesWML.put("tr", WMLTrElementImpl.class);
+ _elementTypesWML.put("go", WMLGoElementImpl.class);
+ _elementTypesWML.put("big", WMLBigElementImpl.class);
+ _elementTypesWML.put("anchor", WMLAnchorElementImpl.class);
+ _elementTypesWML.put("timer", WMLTimerElementImpl.class);
+ _elementTypesWML.put("small", WMLSmallElementImpl.class);
+ _elementTypesWML.put("optgroup", WMLOptgroupElementImpl.class);
+ _elementTypesWML.put("head", WMLHeadElementImpl.class);
+ _elementTypesWML.put("td", WMLTdElementImpl.class);
+ _elementTypesWML.put("fieldset", WMLFieldsetElementImpl.class);
+ _elementTypesWML.put("img", WMLImgElementImpl.class);
+ _elementTypesWML.put("refresh", WMLRefreshElementImpl.class);
+ _elementTypesWML.put("onevent", WMLOneventElementImpl.class);
+ _elementTypesWML.put("input", WMLInputElementImpl.class);
+ _elementTypesWML.put("prev", WMLPrevElementImpl.class);
+ _elementTypesWML.put("table", WMLTableElementImpl.class);
+ _elementTypesWML.put("meta", WMLMetaElementImpl.class);
+ _elementTypesWML.put("template", WMLTemplateElementImpl.class);
+ _elementTypesWML.put("br", WMLBrElementImpl.class);
+ _elementTypesWML.put("option", WMLOptionElementImpl.class);
+ _elementTypesWML.put("u", WMLUElementImpl.class);
+ _elementTypesWML.put("p", WMLPElementImpl.class);
+ _elementTypesWML.put("select", WMLSelectElementImpl.class);
+ _elementTypesWML.put("em", WMLEmElementImpl.class);
+ _elementTypesWML.put("i", WMLIElementImpl.class);
+ _elementTypesWML.put("card", WMLCardElementImpl.class);
+ }
+
+ /* DOM level 2 */
+ public WMLDocumentImpl(DocumentType doctype) {
+ super(doctype, false);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLElementImpl.java
new file mode 100644
index 0000000..a613ea0
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLElementImpl.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLElement;
+import org.apache.xerces.dom.ElementImpl;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLElementImpl extends ElementImpl implements WMLElement {
+
+ private static final long serialVersionUID = 3440984702956371604L;
+
+ public WMLElementImpl (WMLDocumentImpl owner, String tagName) {
+ super(owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ void setAttribute(String attr, boolean value) {
+ setAttribute(attr, value ? "true" : "false");
+ }
+
+ boolean getAttribute(String attr, boolean defaultValue) {
+ boolean ret = defaultValue;
+ String value;
+ if (((value = getAttribute("emptyok")) != null)
+ && value.equals("true"))
+ ret = true;
+ return ret;
+ }
+
+ void setAttribute(String attr, int value) {
+ setAttribute(attr, value + "");
+ }
+
+ int getAttribute(String attr, int defaultValue) {
+ int ret = defaultValue;
+ String value;
+ if ((value = getAttribute("emptyok")) != null)
+ ret = Integer.parseInt(value);
+ return ret;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLEmElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLEmElementImpl.java
new file mode 100644
index 0000000..0b16686
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLEmElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLEmElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLEmElementImpl extends WMLElementImpl implements WMLEmElement {
+
+ private static final long serialVersionUID = 7962278391619830801L;
+
+ public WMLEmElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLFieldsetElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLFieldsetElementImpl.java
new file mode 100644
index 0000000..d51efee
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLFieldsetElementImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLFieldsetElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLFieldsetElementImpl extends WMLElementImpl implements WMLFieldsetElement {
+
+ private static final long serialVersionUID = 6941811812235840705L;
+
+ public WMLFieldsetElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setTitle(String newValue) {
+ setAttribute("title", newValue);
+ }
+
+ public String getTitle() {
+ return getAttribute("title");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLGoElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLGoElementImpl.java
new file mode 100644
index 0000000..020149f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLGoElementImpl.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLGoElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLGoElementImpl extends WMLElementImpl implements WMLGoElement {
+
+ private static final long serialVersionUID = -2052250142899797905L;
+
+ public WMLGoElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setSendreferer(String newValue) {
+ setAttribute("sendreferer", newValue);
+ }
+
+ public String getSendreferer() {
+ return getAttribute("sendreferer");
+ }
+
+ public void setAcceptCharset(String newValue) {
+ setAttribute("accept-charset", newValue);
+ }
+
+ public String getAcceptCharset() {
+ return getAttribute("accept-charset");
+ }
+
+ public void setHref(String newValue) {
+ setAttribute("href", newValue);
+ }
+
+ public String getHref() {
+ return getAttribute("href");
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setMethod(String newValue) {
+ setAttribute("method", newValue);
+ }
+
+ public String getMethod() {
+ return getAttribute("method");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLHeadElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLHeadElementImpl.java
new file mode 100644
index 0000000..68a6b2a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLHeadElementImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLHeadElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLHeadElementImpl extends WMLElementImpl implements WMLHeadElement {
+
+ private static final long serialVersionUID = 3311307374813188908L;
+
+ public WMLHeadElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLIElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLIElementImpl.java
new file mode 100644
index 0000000..0709aa5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLIElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLIElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLIElementImpl extends WMLElementImpl implements WMLIElement {
+
+ private static final long serialVersionUID = 5008873415065802109L;
+
+ public WMLIElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLImgElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLImgElementImpl.java
new file mode 100644
index 0000000..609d268
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLImgElementImpl.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLImgElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLImgElementImpl extends WMLElementImpl implements WMLImgElement {
+
+ private static final long serialVersionUID = -500092034867051550L;
+
+ public WMLImgElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setWidth(String newValue) {
+ setAttribute("width", newValue);
+ }
+
+ public String getWidth() {
+ return getAttribute("width");
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setLocalSrc(String newValue) {
+ setAttribute("localsrc", newValue);
+ }
+
+ public String getLocalSrc() {
+ return getAttribute("localsrc");
+ }
+
+ public void setHeight(String newValue) {
+ setAttribute("height", newValue);
+ }
+
+ public String getHeight() {
+ return getAttribute("height");
+ }
+
+ public void setAlign(String newValue) {
+ setAttribute("align", newValue);
+ }
+
+ public String getAlign() {
+ return getAttribute("align");
+ }
+
+ public void setVspace(String newValue) {
+ setAttribute("vspace", newValue);
+ }
+
+ public String getVspace() {
+ return getAttribute("vspace");
+ }
+
+ public void setAlt(String newValue) {
+ setAttribute("alt", newValue);
+ }
+
+ public String getAlt() {
+ return getAttribute("alt");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setHspace(String newValue) {
+ setAttribute("hspace", newValue);
+ }
+
+ public String getHspace() {
+ return getAttribute("hspace");
+ }
+
+ public void setSrc(String newValue) {
+ setAttribute("src", newValue);
+ }
+
+ public String getSrc() {
+ return getAttribute("src");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLInputElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLInputElementImpl.java
new file mode 100644
index 0000000..fc041bb
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLInputElementImpl.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLInputElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLInputElementImpl extends WMLElementImpl implements WMLInputElement {
+
+ private static final long serialVersionUID = 2897319793637966619L;
+
+ public WMLInputElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setSize(int newValue) {
+ setAttribute("size", newValue);
+ }
+
+ public int getSize() {
+ return getAttribute("size", 0);
+ }
+
+ public void setFormat(String newValue) {
+ setAttribute("format", newValue);
+ }
+
+ public String getFormat() {
+ return getAttribute("format");
+ }
+
+ public void setValue(String newValue) {
+ setAttribute("value", newValue);
+ }
+
+ public String getValue() {
+ return getAttribute("value");
+ }
+
+ public void setMaxLength(int newValue) {
+ setAttribute("maxlength", newValue);
+ }
+
+ public int getMaxLength() {
+ return getAttribute("maxlength", 0);
+ }
+
+ public void setTabIndex(int newValue) {
+ setAttribute("tabindex", newValue);
+ }
+
+ public int getTabIndex() {
+ return getAttribute("tabindex", 0);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setEmptyOk(boolean newValue) {
+ setAttribute("emptyok", newValue);
+ }
+
+ public boolean getEmptyOk() {
+ return getAttribute("emptyok", false);
+ }
+
+ public void setTitle(String newValue) {
+ setAttribute("title", newValue);
+ }
+
+ public String getTitle() {
+ return getAttribute("title");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setType(String newValue) {
+ setAttribute("type", newValue);
+ }
+
+ public String getType() {
+ return getAttribute("type");
+ }
+
+ public void setName(String newValue) {
+ setAttribute("name", newValue);
+ }
+
+ public String getName() {
+ return getAttribute("name");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLMetaElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLMetaElementImpl.java
new file mode 100644
index 0000000..8877b14
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLMetaElementImpl.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLMetaElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLMetaElementImpl extends WMLElementImpl implements WMLMetaElement {
+
+ private static final long serialVersionUID = -2791663042188681846L;
+
+ public WMLMetaElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setForua(boolean newValue) {
+ setAttribute("forua", newValue);
+ }
+
+ public boolean getForua() {
+ return getAttribute("forua", false);
+ }
+
+ public void setScheme(String newValue) {
+ setAttribute("scheme", newValue);
+ }
+
+ public String getScheme() {
+ return getAttribute("scheme");
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setHttpEquiv(String newValue) {
+ setAttribute("http-equiv", newValue);
+ }
+
+ public String getHttpEquiv() {
+ return getAttribute("http-equiv");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setContent(String newValue) {
+ setAttribute("content", newValue);
+ }
+
+ public String getContent() {
+ return getAttribute("content");
+ }
+
+ public void setName(String newValue) {
+ setAttribute("name", newValue);
+ }
+
+ public String getName() {
+ return getAttribute("name");
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLNoopElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLNoopElementImpl.java
new file mode 100644
index 0000000..f8e90ab
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLNoopElementImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLNoopElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLNoopElementImpl extends WMLElementImpl implements WMLNoopElement {
+
+ private static final long serialVersionUID = -1581314434256075931L;
+
+ public WMLNoopElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLOneventElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLOneventElementImpl.java
new file mode 100644
index 0000000..3fab7ee
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLOneventElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLOneventElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLOneventElementImpl extends WMLElementImpl implements WMLOneventElement {
+
+ private static final long serialVersionUID = -4279215241146570871L;
+
+ public WMLOneventElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setType(String newValue) {
+ setAttribute("type", newValue);
+ }
+
+ public String getType() {
+ return getAttribute("type");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLOptgroupElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLOptgroupElementImpl.java
new file mode 100644
index 0000000..9d45d52
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLOptgroupElementImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLOptgroupElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLOptgroupElementImpl extends WMLElementImpl implements WMLOptgroupElement {
+
+ private static final long serialVersionUID = 1592761119479339142L;
+
+ public WMLOptgroupElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setTitle(String newValue) {
+ setAttribute("title", newValue);
+ }
+
+ public String getTitle() {
+ return getAttribute("title");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLOptionElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLOptionElementImpl.java
new file mode 100644
index 0000000..0486988
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLOptionElementImpl.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLOptionElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLOptionElementImpl extends WMLElementImpl implements WMLOptionElement {
+
+ private static final long serialVersionUID = -3432299264888771937L;
+
+ public WMLOptionElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setValue(String newValue) {
+ setAttribute("value", newValue);
+ }
+
+ public String getValue() {
+ return getAttribute("value");
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setTitle(String newValue) {
+ setAttribute("title", newValue);
+ }
+
+ public String getTitle() {
+ return getAttribute("title");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setOnPick(String newValue) {
+ setAttribute("onpick", newValue);
+ }
+
+ public String getOnPick() {
+ return getAttribute("onpick");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLPElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLPElementImpl.java
new file mode 100644
index 0000000..5690303
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLPElementImpl.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLPElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLPElementImpl extends WMLElementImpl implements WMLPElement {
+
+ private static final long serialVersionUID = 4263257796458499960L;
+
+ public WMLPElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setMode(String newValue) {
+ setAttribute("mode", newValue);
+ }
+
+ public String getMode() {
+ return getAttribute("mode");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setAlign(String newValue) {
+ setAttribute("align", newValue);
+ }
+
+ public String getAlign() {
+ return getAttribute("align");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLPostfieldElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLPostfieldElementImpl.java
new file mode 100644
index 0000000..d660725
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLPostfieldElementImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLPostfieldElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLPostfieldElementImpl extends WMLElementImpl implements WMLPostfieldElement {
+
+ private static final long serialVersionUID = -1169432003991642980L;
+
+ public WMLPostfieldElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setValue(String newValue) {
+ setAttribute("value", newValue);
+ }
+
+ public String getValue() {
+ return getAttribute("value");
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setName(String newValue) {
+ setAttribute("name", newValue);
+ }
+
+ public String getName() {
+ return getAttribute("name");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLPrevElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLPrevElementImpl.java
new file mode 100644
index 0000000..bdb9cec
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLPrevElementImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLPrevElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLPrevElementImpl extends WMLElementImpl implements WMLPrevElement {
+
+ private static final long serialVersionUID = -1545713716925433554L;
+
+ public WMLPrevElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLRefreshElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLRefreshElementImpl.java
new file mode 100644
index 0000000..b306685
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLRefreshElementImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLRefreshElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLRefreshElementImpl extends WMLElementImpl implements WMLRefreshElement {
+
+ private static final long serialVersionUID = 8781837880806459398L;
+
+ public WMLRefreshElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLSelectElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLSelectElementImpl.java
new file mode 100644
index 0000000..758277a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLSelectElementImpl.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLSelectElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLSelectElementImpl extends WMLElementImpl implements WMLSelectElement {
+
+ private static final long serialVersionUID = 6489112443257247261L;
+
+ public WMLSelectElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setMultiple(boolean newValue) {
+ setAttribute("multiple", newValue);
+ }
+
+ public boolean getMultiple() {
+ return getAttribute("multiple", false);
+ }
+
+ public void setValue(String newValue) {
+ setAttribute("value", newValue);
+ }
+
+ public String getValue() {
+ return getAttribute("value");
+ }
+
+ public void setTabIndex(int newValue) {
+ setAttribute("tabindex", newValue);
+ }
+
+ public int getTabIndex() {
+ return getAttribute("tabindex", 0);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setTitle(String newValue) {
+ setAttribute("title", newValue);
+ }
+
+ public String getTitle() {
+ return getAttribute("title");
+ }
+
+ public void setIValue(String newValue) {
+ setAttribute("ivalue", newValue);
+ }
+
+ public String getIValue() {
+ return getAttribute("ivalue");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setIName(String newValue) {
+ setAttribute("iname", newValue);
+ }
+
+ public String getIName() {
+ return getAttribute("iname");
+ }
+
+ public void setName(String newValue) {
+ setAttribute("name", newValue);
+ }
+
+ public String getName() {
+ return getAttribute("name");
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLSetvarElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLSetvarElementImpl.java
new file mode 100644
index 0000000..ff044e2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLSetvarElementImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLSetvarElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLSetvarElementImpl extends WMLElementImpl implements WMLSetvarElement {
+
+ private static final long serialVersionUID = -1944519734782236471L;
+
+ public WMLSetvarElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setValue(String newValue) {
+ setAttribute("value", newValue);
+ }
+
+ public String getValue() {
+ return getAttribute("value");
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setName(String newValue) {
+ setAttribute("name", newValue);
+ }
+
+ public String getName() {
+ return getAttribute("name");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLSmallElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLSmallElementImpl.java
new file mode 100644
index 0000000..baf9351
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLSmallElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLSmallElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLSmallElementImpl extends WMLElementImpl implements WMLSmallElement {
+
+ private static final long serialVersionUID = 2654490940644799492L;
+
+ public WMLSmallElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLStrongElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLStrongElementImpl.java
new file mode 100644
index 0000000..08fcd57
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLStrongElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLStrongElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLStrongElementImpl extends WMLElementImpl implements WMLStrongElement {
+
+ private static final long serialVersionUID = 8451363815747099580L;
+
+ public WMLStrongElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLTableElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLTableElementImpl.java
new file mode 100644
index 0000000..16ea366
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLTableElementImpl.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLTableElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLTableElementImpl extends WMLElementImpl implements WMLTableElement {
+
+ private static final long serialVersionUID = 7676208849347355339L;
+
+ public WMLTableElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setColumns(int newValue) {
+ setAttribute("columns", newValue);
+ }
+
+ public int getColumns() {
+ return getAttribute("columns", 0);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setAlign(String newValue) {
+ setAttribute("align", newValue);
+ }
+
+ public String getAlign() {
+ return getAttribute("align");
+ }
+
+ public void setTitle(String newValue) {
+ setAttribute("title", newValue);
+ }
+
+ public String getTitle() {
+ return getAttribute("title");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLTdElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLTdElementImpl.java
new file mode 100644
index 0000000..ea52071
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLTdElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLTdElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLTdElementImpl extends WMLElementImpl implements WMLTdElement {
+
+ private static final long serialVersionUID = 6074218675876025710L;
+
+ public WMLTdElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLTemplateElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLTemplateElementImpl.java
new file mode 100644
index 0000000..e8440ae
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLTemplateElementImpl.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLTemplateElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLTemplateElementImpl extends WMLElementImpl implements WMLTemplateElement {
+
+ private static final long serialVersionUID = 4231732841621131049L;
+
+ public WMLTemplateElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setOnTimer(String newValue) {
+ setAttribute("ontimer", newValue);
+ }
+
+ public String getOnTimer() {
+ return getAttribute("ontimer");
+ }
+
+ public void setOnEnterBackward(String newValue) {
+ setAttribute("onenterbackward", newValue);
+ }
+
+ public String getOnEnterBackward() {
+ return getAttribute("onenterbackward");
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setOnEnterForward(String newValue) {
+ setAttribute("onenterforward", newValue);
+ }
+
+ public String getOnEnterForward() {
+ return getAttribute("onenterforward");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLTimerElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLTimerElementImpl.java
new file mode 100644
index 0000000..8e96ebc
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLTimerElementImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLTimerElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLTimerElementImpl extends WMLElementImpl implements WMLTimerElement {
+
+ private static final long serialVersionUID = 9055622169756832726L;
+
+ public WMLTimerElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setValue(String newValue) {
+ setAttribute("value", newValue);
+ }
+
+ public String getValue() {
+ return getAttribute("value");
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+ public void setName(String newValue) {
+ setAttribute("name", newValue);
+ }
+
+ public String getName() {
+ return getAttribute("name");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLTrElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLTrElementImpl.java
new file mode 100644
index 0000000..6a8eaed
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLTrElementImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLTrElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLTrElementImpl extends WMLElementImpl implements WMLTrElement {
+
+ private static final long serialVersionUID = -4304021232051604343L;
+
+ public WMLTrElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLUElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLUElementImpl.java
new file mode 100644
index 0000000..9553c48
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLUElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLUElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLUElementImpl extends WMLElementImpl implements WMLUElement {
+
+ private static final long serialVersionUID = 6350194387815102797L;
+
+ public WMLUElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/wml/dom/WMLWmlElementImpl.java b/resources/xerces2-j-src/org/apache/wml/dom/WMLWmlElementImpl.java
new file mode 100644
index 0000000..817fd48
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/wml/dom/WMLWmlElementImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wml.dom;
+
+import org.apache.wml.WMLWmlElement;
+
+/**
+ * @xerces.internal
+ * @version $Id$
+ * @author David Li
+ */
+public class WMLWmlElementImpl extends WMLElementImpl implements WMLWmlElement {
+
+ private static final long serialVersionUID = -7008023851895920651L;
+
+ public WMLWmlElementImpl (WMLDocumentImpl owner, String tagName) {
+ super( owner, tagName);
+ }
+
+ public void setClassName(String newValue) {
+ setAttribute("class", newValue);
+ }
+
+ public String getClassName() {
+ return getAttribute("class");
+ }
+
+ public void setXmlLang(String newValue) {
+ setAttribute("xml:lang", newValue);
+ }
+
+ public String getXmlLang() {
+ return getAttribute("xml:lang");
+ }
+
+ public void setId(String newValue) {
+ setAttribute("id", newValue);
+ }
+
+ public String getId() {
+ return getAttribute("id");
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/ASDOMImplementationImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/ASDOMImplementationImpl.java
new file mode 100644
index 0000000..2239154
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/ASDOMImplementationImpl.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.apache.xerces.dom3.as.ASModel;
+import org.apache.xerces.dom3.as.DOMASBuilder;
+import org.apache.xerces.dom3.as.DOMASWriter;
+import org.apache.xerces.dom3.as.DOMImplementationAS;
+import org.apache.xerces.parsers.DOMASBuilderImpl;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+
+
+
+/**
+ * The DOMImplementation class is description of a particular
+ * implementation of the Document Object Model. As such its data is
+ * static, shared by all instances of this implementation.
+ *
+ * The DOM API requires that it be a real object rather than static
+ * methods. However, there's nothing that says it can't be a singleton,
+ * so that's how I've implemented it.
+ *
+ * This particular class, along with DocumentImpl, supports the DOM
+ * Core, DOM Level 2 optional mofules, and Abstract Schemas (Experimental).
+ * @deprecated
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class ASDOMImplementationImpl extends DOMImplementationImpl
+ implements DOMImplementationAS {
+
+
+ // static
+
+ /** Dom implementation singleton. */
+ static final ASDOMImplementationImpl singleton = new ASDOMImplementationImpl();
+
+
+ //
+ // Public methods
+ //
+
+ /** NON-DOM: Obtain and return the single shared object */
+ public static DOMImplementation getDOMImplementation() {
+ return singleton;
+ }
+
+ //
+ // DOM L3 Abstract Schemas:
+ // REVISIT: implement hasFeature()
+ //
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * Creates an ASModel.
+ * @param isNamespaceAware Allow creation of ASModel with
+ * this attribute set to a specific value.
+ * @return A null return indicates failure.what is a
+ * failure? Could be a system error.
+ */
+ public ASModel createAS(boolean isNamespaceAware){
+ return new ASModelImpl(isNamespaceAware);
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * Creates an DOMASBuilder .Do we need the method since we
+ * already have DOMImplementationLS.createDOMParser ?
+ * @return DOMASBuilder
+ */
+ public DOMASBuilder createDOMASBuilder(){
+ return new DOMASBuilderImpl();
+ }
+
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * Creates an DOMASWriter .
+ * @return a DOMASWriter
+ */
+ public DOMASWriter createDOMASWriter(){
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+
+
+} // class DOMImplementationImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/ASModelImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/ASModelImpl.java
new file mode 100644
index 0000000..c1b0f99
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/ASModelImpl.java
@@ -0,0 +1,498 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.util.Vector;
+
+import org.apache.xerces.dom3.as.ASAttributeDeclaration;
+import org.apache.xerces.dom3.as.ASContentModel;
+import org.apache.xerces.dom3.as.ASElementDeclaration;
+import org.apache.xerces.dom3.as.ASEntityDeclaration;
+import org.apache.xerces.dom3.as.ASModel;
+import org.apache.xerces.dom3.as.ASNamedObjectMap;
+import org.apache.xerces.dom3.as.ASNotationDeclaration;
+import org.apache.xerces.dom3.as.ASObject;
+import org.apache.xerces.dom3.as.ASObjectList;
+import org.apache.xerces.dom3.as.DOMASException;
+import org.apache.xerces.impl.xs.SchemaGrammar;
+import org.w3c.dom.DOMException;
+
+/**
+ * To begin with, an abstract schema is a generic structure that could
+ * contain both internal and external subsets. An ASModel is an
+ * abstract object that could map to a DTD , an XML Schema , a database
+ * schema, etc. An ASModel could represent either an internal
+ * or an external subset; hence an abstract schema could be composed of an
+ * ASModel representing the internal subset and an
+ * ASModel representing the external subset. Note that the
+ * ASModel representing the external subset could consult the
+ * ASModel representing the internal subset. Furthermore, the
+ * ASModel representing the internal subset could be set to
+ * null by the setInternalAS method as a mechanism for
+ * "removal". In addition, only one ASModel representing the
+ * external subset can be specified as "active" and it is possible that none
+ * are "active". Finally, the ASModel contains the factory
+ * methods needed to create a various types of ASObjects like
+ * ASElementDeclaration , ASAttributeDeclaration ,
+ * etc.
+ * See also the
+ * Document Object Model (DOM) Level 3 Abstract Schemas and Load and Save Specification.
+ * @deprecated
+ * @author Pavani Mukthipudi
+ * @author Neil Graham
+ * @version $Id$
+ */
+public class ASModelImpl implements ASModel {
+
+ //
+ // Data
+ //
+ boolean fNamespaceAware = true;
+
+ // conceptually, an ASModel may contain grammar information and/or
+ // other ASModels. These two fields divide that function.
+ protected Vector fASModels;
+ protected SchemaGrammar fGrammar = null;
+
+ //
+ // Constructors
+ //
+
+ public ASModelImpl() {
+ fASModels = new Vector();
+ }
+
+ public ASModelImpl(boolean isNamespaceAware) {
+ fASModels = new Vector();
+ fNamespaceAware = isNamespaceAware;
+ }
+
+ //
+ // ASObject methods
+ //
+
+ /**
+ * A code representing the underlying object as defined above.
+ */
+ public short getAsNodeType() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * The ASModel object associated with this
+ * ASObject . For a node of type AS_MODEL , this
+ * is null .
+ */
+ public ASModel getOwnerASModel() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * The ASModel object associated with this
+ * ASObject . For a node of type AS_MODEL , this
+ * is null .
+ */
+ public void setOwnerASModel(ASModel ownerASModel) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * The name of this ASObject depending on the
+ * ASObject type.
+ */
+ public String getNodeName() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * The name of this ASObject depending on the
+ * ASObject type.
+ */
+ public void setNodeName(String nodeName) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * The namespace prefix of this node, or null if it is
+ * unspecified.
+ */
+ public String getPrefix() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * The namespace prefix of this node, or null if it is
+ * unspecified.
+ */
+ public void setPrefix(String prefix) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Returns the local part of the qualified name of this
+ * ASObject .
+ */
+ public String getLocalName() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Returns the local part of the qualified name of this
+ * ASObject .
+ */
+ public void setLocalName(String localName) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * The namespace URI of this node, or null if it is
+ * unspecified. defines how a namespace URI is attached to schema
+ * components.
+ */
+ public String getNamespaceURI() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * The namespace URI of this node, or null if it is
+ * unspecified. defines how a namespace URI is attached to schema
+ * components.
+ */
+ public void setNamespaceURI(String namespaceURI) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Creates a copy of this ASObject . See text for
+ * cloneNode off of Node but substitute AS
+ * functionality.
+ * @param deep Setting the deep flag on, causes the whole
+ * subtree to be duplicated. Setting it to false only
+ * duplicates its immediate child nodes.
+ * @return Cloned ASObject .
+ */
+ public ASObject cloneASObject(boolean deep) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ //
+ // ASModel methods
+ //
+
+ /**
+ * true if this ASModel defines the document
+ * structure in terms of namespaces and local names ; false
+ * if the document structure is defined only in terms of
+ * QNames .
+ */
+ public boolean getIsNamespaceAware() {
+ return fNamespaceAware;
+ }
+
+ /**
+ * 0 if used internally, 1 if used externally, 2 if not all. An exception
+ * will be raised if it is incompatibly shared or in use as an internal
+ * subset.
+ */
+ public short getUsageLocation() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * The URI reference.
+ */
+ public String getAsLocation() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * The URI reference.
+ */
+ public void setAsLocation(String asLocation) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * The hint to locating an ASModel.
+ */
+ public String getAsHint() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * The hint to locating an ASModel.
+ */
+ public void setAsHint(String asHint) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * If usage is EXTERNAL_SUBSET or NOT_USED, and the
+ * ASModel is simply a container of other ASModels.
+ */
+ public boolean getContainer() {
+ return (fGrammar != null);
+ }
+
+ /**
+ * Instead of returning an all-in-one ASObject with
+ * ASModel methods, have discernible top-level/"global"
+ * element declarations. If one attempts to add, set, or remove a node
+ * type other than the intended one, a hierarchy exception (or
+ * equivalent is thrown).
+ */
+ public ASNamedObjectMap getElementDeclarations() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Instead of returning an all-in-one ASObject with
+ * ASModel methods, have discernible top-level/"global"
+ * attribute declarations. If one attempts to add, set, or remove a node
+ * type other than the intended one, a hierarchy exception (or
+ * equivalent is thrown).
+ */
+ public ASNamedObjectMap getAttributeDeclarations() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Instead of returning an all-in-one ASObject with
+ * ASModel methods, have discernible top-level/"global"
+ * notation declarations. If one attempts to add, set, or remove a node
+ * type other than the intended one, a hierarchy exception (or
+ * equivalent is thrown).
+ */
+ public ASNamedObjectMap getNotationDeclarations() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Instead of returning an all-in-one ASObject with
+ * ASModel methods, have discernible top-level/"global"
+ * entity declarations. If one attempts to add, set, or remove a node
+ * type other than the intended one, a hierarchy exception (or
+ * equivalent is thrown).
+ */
+ public ASNamedObjectMap getEntityDeclarations() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Instead of returning an all-in-one ASObject with
+ * ASModel methods, have discernible top-level/"global
+ * content model declarations. If one attempts to add, set, or remove a
+ * node type other than the intended one, a hierarchy exception (or
+ * equivalent is thrown).
+ */
+ public ASNamedObjectMap getContentModelDeclarations() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * This method will allow the nesting or "importation" of ASModels.
+ * @param abstractSchema ASModel to be set. Subsequent calls will nest
+ * the ASModels within the specified ownerASModel .
+ */
+ public void addASModel(ASModel abstractSchema) {
+ fASModels.addElement(abstractSchema);
+ }
+
+ /**
+ * To retrieve a list of nested ASModels without reference to names.
+ * @return A list of ASModels.
+ */
+ public ASObjectList getASModels() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Removes only the specified ASModel from the list of
+ * ASModel s.
+ * @param as AS to be removed.
+ */
+ public void removeAS(ASModel as) {
+ fASModels.removeElement(as);
+ }
+
+ /**
+ * Determines if an ASModel itself is valid, i.e., confirming
+ * that it's well-formed and valid per its own formal grammar.
+ * @return true if the ASModel is valid,
+ * false otherwise.
+ */
+ public boolean validate() {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Imports ASObject into ASModel.
+ * @param asobject ASObject to be imported.
+ */
+ public void importASObject(ASObject asobject) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Inserts ASObject into ASModel.
+ * @param asobject ASObject to be inserted.
+ */
+ public void insertASObject(ASObject asobject) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Creates an element declaration for the element type specified.
+ * @param namespaceURI The namespace URI of the element type
+ * being declared.
+ * @param name The name of the element. The format of the name could be
+ * an NCName as defined by XML Namespaces or a Name as defined by XML
+ * 1.0; it's ASModel-dependent.
+ * @return A new ASElementDeclaration object with
+ * name attribute set to tagname and
+ * namespaceURI set to systemId . Other
+ * attributes of the element declaration are set through
+ * ASElementDeclaration interface methods.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * illegal character.
+ */
+ public ASElementDeclaration createASElementDeclaration(String namespaceURI,
+ String name)
+ throws DOMException {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Creates an attribute declaration.
+ * @param namespaceURI The namespace URI of the attribute being declared.
+ * @param name The name of the attribute. The format of the name could be
+ * an NCName as defined by XML Namespaces or a Name as defined by XML
+ * 1.0; it's ASModel-dependent.
+ * @return A new ASAttributeDeclaration object with
+ * appropriate attributes set by input parameters.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the input name
+ * parameter contains an illegal character.
+ */
+ public ASAttributeDeclaration createASAttributeDeclaration(String namespaceURI,
+ String name)
+ throws DOMException {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Creates a new notation declaration.
+ * @param namespaceURI The namespace URI of the notation being declared.
+ * @param name The name of the notation. The format of the name could be
+ * an NCName as defined by XML Namespaces or a Name as defined by XML
+ * 1.0; it's ASModel-dependent.
+ * @param systemId The system identifier for the notation declaration.
+ * @param publicId The public identifier for the notation declaration.
+ * @return A new ASNotationDeclaration object with
+ * notationName attribute set to name and
+ * publicId and systemId set to the
+ * corresponding fields.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * illegal character.
+ */
+ public ASNotationDeclaration createASNotationDeclaration(String namespaceURI, String name,
+ String systemId, String publicId)
+ throws DOMException {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Creates an ASEntityDeclaration.
+ * @param name The name of the entity being declared.
+ * @return A new ASEntityDeclaration object with
+ * entityName attribute set to name.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * illegal character.
+ */
+ public ASEntityDeclaration createASEntityDeclaration(String name)
+ throws DOMException {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ /**
+ * Creates an object which describes part of an
+ * ASElementDeclaration 's content model.
+ * @param minOccurs The minimum occurrence for the subModels of this
+ * ASContentModel .
+ * @param maxOccurs The maximum occurrence for the subModels of this
+ * ASContentModel .
+ * @param operator operator of type AS_CHOICE ,
+ * AS_SEQUENCE , AS_ALL or
+ * AS_NONE .
+ * @return A new ASContentModel object.
+ * @exception DOMASException
+ * A DOMASException, e.g., minOccurs > maxOccurs .
+ */
+ public ASContentModel createASContentModel(int minOccurs, int maxOccurs,
+ short operator) throws DOMASException {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+
+ // convenience methods
+ public SchemaGrammar getGrammar() {
+ return fGrammar;
+ }
+ public void setGrammar(SchemaGrammar grammar) {
+ fGrammar = grammar;
+ }
+
+ public Vector getInternalASModels() {
+ return fASModels;
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/AttrImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/AttrImpl.java
new file mode 100644
index 0000000..5166148
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/AttrImpl.java
@@ -0,0 +1,1237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.w3c.dom.TypeInfo;
+
+/**
+ * Attribute represents an XML-style attribute of an
+ * Element. Typically, the allowable values are controlled by its
+ * declaration in the Document Type Definition (DTD) governing this
+ * kind of document.
+ *
+ * If the attribute has not been explicitly assigned a value, but has
+ * been declared in the DTD, it will exist and have that default. Only
+ * if neither the document nor the DTD specifies a value will the
+ * Attribute really be considered absent and have no value; in that
+ * case, querying the attribute will return null.
+ *
+ * Attributes may have multiple children that contain their data. (XML
+ * allows attributes to contain entity references, and tokenized
+ * attribute types such as NMTOKENS may have a child for each token.)
+ * For convenience, the Attribute object's getValue() method returns
+ * the string version of the attribute's value.
+ *
+ * Attributes are not children of the Elements they belong to, in the
+ * usual sense, and have no valid Parent reference. However, the spec
+ * says they _do_ belong to a specific Element, and an INUSE exception
+ * is to be thrown if the user attempts to explicitly share them
+ * between elements.
+ *
+ * Note that Elements do not permit attributes to appear to be shared
+ * (see the INUSE exception), so this object's mutability is
+ * officially not an issue.
+ *
+ * Note: The ownerNode attribute is used to store the Element the Attr
+ * node is associated with. Attr nodes do not have parent nodes.
+ * Besides, the getOwnerElement() method can be used to get the element node
+ * this attribute is associated with.
+ *
+ * AttrImpl does not support Namespaces. AttrNSImpl, which inherits from
+ * it, does.
+ *
+ * AttrImpl used to inherit from ParentNode. It now directly inherits from
+ * NodeImpl and provide its own implementation of the ParentNode's behavior.
+ * The reason is that we now try and avoid to always create a Text node to
+ * hold the value of an attribute. The DOM spec requires it, so we still have
+ * to do it in case getFirstChild() is called for instance. The reason
+ * attribute values are stored as a list of nodes is so that they can carry
+ * more than a simple string. They can also contain EntityReference nodes.
+ * However, most of the times people only have a single string that they only
+ * set and get through Element.set/getAttribute or Attr.set/getValue. In this
+ * new version, the Attr node has a value pointer which can either be the
+ * String directly or a pointer to the first ChildNode. A flag tells which one
+ * it currently is. Note that while we try to stick with the direct String as
+ * much as possible once we've switched to a node there is no going back. This
+ * is because we have no way to know whether the application keeps referring to
+ * the node we once returned.
+ * The gain in memory varies on the density of attributes in the document.
+ * But in the tests I've run I've seen up to 12% of memory gain. And the good
+ * thing is that it also leads to a slight gain in speed because we allocate
+ * fewer objects! I mean, that's until we have to actually create the node...
+ *
+ * To avoid too much duplicated code, I got rid of ParentNode and renamed
+ * ChildAndParentNode, which I never really liked, to ParentNode for
+ * simplicity, this doesn't make much of a difference in memory usage because
+ * there are only very few objects that are only a Parent. This is only true
+ * now because AttrImpl now inherits directly from NodeImpl and has its own
+ * implementation of the ParentNode's node behavior. So there is still some
+ * duplicated code there.
+ *
+ * This class doesn't directly support mutation events, however, it notifies
+ * the document when mutations are performed so that the document class do so.
+ *
+ * WARNING: Some of the code here is partially duplicated in
+ * ParentNode, be careful to keep these two classes in sync!
+ *
+ * @xerces.internal
+ *
+ * @see AttrNSImpl
+ *
+ * @author Arnaud Le Hors, IBM
+ * @author Joe Kesselman, IBM
+ * @author Andy Clark, IBM
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ *
+ */
+public class AttrImpl
+ extends NodeImpl
+ implements Attr, TypeInfo{
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 7277707688218972102L;
+
+ /** DTD namespace. **/
+ static final String DTD_URI = "http://www.w3.org/TR/REC-xml";
+
+ //
+ // Data
+ //
+
+ /** This can either be a String or the first child node. */
+ protected Object value = null;
+
+ /** Attribute name. */
+ protected String name;
+
+ /** Type information */
+ // REVISIT: we are losing the type information in DOM during serialization
+ transient Object type;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Attribute has no public constructor. Please use the factory
+ * method in the Document class.
+ */
+ protected AttrImpl(CoreDocumentImpl ownerDocument, String name) {
+ super(ownerDocument);
+ this.name = name;
+ /** False for default attributes. */
+ isSpecified(true);
+ hasStringValue(true);
+ }
+
+ // for AttrNSImpl
+ protected AttrImpl() {}
+
+ // Support for DOM Level 3 renameNode method.
+ // Note: This only deals with part of the pb. It is expected to be
+ // called after the Attr has been detached for one thing.
+ // CoreDocumentImpl does all the work.
+ void rename(String name) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ this.name = name;
+ }
+
+ // create a real text node as child if we don't have one yet
+ protected void makeChildNode() {
+ if (hasStringValue()) {
+ if (value != null) {
+ TextImpl text =
+ (TextImpl) ownerDocument().createTextNode((String) value);
+ value = text;
+ text.isFirstChild(true);
+ text.previousSibling = text;
+ text.ownerNode = this;
+ text.isOwned(true);
+ }
+ hasStringValue(false);
+ }
+ }
+
+ /**
+ * NON-DOM
+ * set the ownerDocument of this node and its children
+ */
+ protected void setOwnerDocument(CoreDocumentImpl doc) {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ super.setOwnerDocument(doc);
+ if (!hasStringValue()) {
+ for (ChildNode child = (ChildNode) value;
+ child != null; child = child.nextSibling) {
+ child.setOwnerDocument(doc);
+ }
+ }
+ }
+
+ /**
+ * NON-DOM: set the type of this attribute to be ID type.
+ *
+ * @param id
+ */
+ public void setIdAttribute(boolean id){
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ isIdAttribute(id);
+ }
+ /** DOM Level 3: isId*/
+ public boolean isId(){
+ // REVISIT: should an attribute that is not in the tree return
+ // isID true?
+ return isIdAttribute();
+ }
+
+
+ //
+ // Node methods
+ //
+
+ public Node cloneNode(boolean deep) {
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ AttrImpl clone = (AttrImpl) super.cloneNode(deep);
+
+ // take care of case where there are kids
+ if (!clone.hasStringValue()) {
+
+ // Need to break the association w/ original kids
+ clone.value = null;
+
+ // Cloning an Attribute always clones its children,
+ // since they represent its value, no matter whether this
+ // is a deep clone or not
+ for (Node child = (Node) value; child != null;
+ child = child.getNextSibling()) {
+ clone.appendChild(child.cloneNode(true));
+ }
+ }
+ clone.isSpecified(true);
+ return clone;
+ }
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public short getNodeType() {
+ return Node.ATTRIBUTE_NODE;
+ }
+
+ /**
+ * Returns the attribute name
+ */
+ public String getNodeName() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return name;
+ }
+
+ /**
+ * Implicit in the rerouting of getNodeValue to getValue is the
+ * need to redefine setNodeValue, for symmetry's sake. Note that
+ * since we're explicitly providing a value, Specified should be set
+ * true.... even if that value equals the default.
+ */
+ public void setNodeValue(String value) throws DOMException {
+ setValue(value);
+ }
+
+ /**
+ * @see org.w3c.dom.TypeInfo#getTypeName()
+ */
+ public String getTypeName() {
+ return (String)type;
+ }
+
+ /**
+ * @see org.w3c.dom.TypeInfo#getTypeNamespace()
+ */
+ public String getTypeNamespace() {
+ if (type != null) {
+ return DTD_URI;
+ }
+ return null;
+ }
+
+ /**
+ * Method getSchemaTypeInfo.
+ * @return TypeInfo
+ */
+ public TypeInfo getSchemaTypeInfo(){
+ return this;
+ }
+
+ /**
+ * In Attribute objects, NodeValue is considered a synonym for
+ * Value.
+ *
+ * @see #getValue()
+ */
+ public String getNodeValue() {
+ return getValue();
+ }
+
+ //
+ // Attr methods
+ //
+
+ /**
+ * In Attributes, NodeName is considered a synonym for the
+ * attribute's Name
+ */
+ public String getName() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return name;
+
+ } // getName():String
+
+ /**
+ * The DOM doesn't clearly define what setValue(null) means. I've taken it
+ * as "remove all children", which from outside should appear
+ * similar to setting it to the empty string.
+ */
+ public void setValue(String newvalue) {
+
+ CoreDocumentImpl ownerDocument = ownerDocument();
+
+ if (ownerDocument.errorChecking && isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+
+ Element ownerElement = getOwnerElement();
+ String oldvalue = "";
+ TextImpl textNode = null;
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ if (value != null) {
+ if (ownerDocument.getMutationEvents()) {
+ // Can no longer just discard the kids; they may have
+ // event listeners waiting for them to disconnect.
+ if (hasStringValue()) {
+ oldvalue = (String) value;
+ // create an actual text node as our child so
+ // that we can use it in the event
+ textNode = (TextImpl) ownerDocument.createTextNode((String) value);
+ value = textNode;
+ textNode.isFirstChild(true);
+ textNode.previousSibling = textNode;
+ textNode.ownerNode = this;
+ textNode.isOwned(true);
+ hasStringValue(false);
+ internalRemoveChild(textNode, true);
+ }
+ else {
+ oldvalue = getValue();
+ while (value != null) {
+ internalRemoveChild((Node) value, true);
+ }
+ }
+ }
+ else {
+ if (hasStringValue()) {
+ oldvalue = (String) value;
+ }
+ else {
+ // simply discard children if any
+ oldvalue = getValue();
+ // remove ref from first child to last child
+ ChildNode firstChild = (ChildNode) value;
+ firstChild.previousSibling = null;
+ firstChild.isFirstChild(false);
+ firstChild.ownerNode = ownerDocument;
+ }
+ // then remove ref to current value
+ value = null;
+ needsSyncChildren(false);
+ }
+ if (isIdAttribute() && ownerElement != null) {
+ ownerDocument.removeIdentifier(oldvalue);
+ }
+ }
+
+ // Create and add the new one, generating only non-aggregate events
+ // (There are no listeners on the new Text, but there may be
+ // capture/bubble listeners on the Attr.
+ // Note that aggregate events are NOT dispatched here,
+ // since we need to combine the remove and insert.
+ isSpecified(true);
+ if (ownerDocument.getMutationEvents()) {
+ // if there are any event handlers create a real node or
+ // reuse the one we synthesized for the remove notifications
+ // if it exists.
+ if (textNode == null) {
+ textNode = (TextImpl) ownerDocument.createTextNode(newvalue);
+ }
+ else {
+ textNode.data = newvalue;
+ }
+ internalInsertBefore(textNode, null, true);
+ hasStringValue(false);
+ // notify document
+ ownerDocument.modifiedAttrValue(this, oldvalue);
+ } else {
+ // directly store the string
+ value = newvalue;
+ hasStringValue(true);
+ changed();
+ }
+ if (isIdAttribute() && ownerElement != null) {
+ ownerDocument.putIdentifier(newvalue, ownerElement);
+ }
+
+ } // setValue(String)
+
+ /**
+ * The "string value" of an Attribute is its text representation,
+ * which in turn is a concatenation of the string values of its children.
+ */
+ public String getValue() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ if (value == null) {
+ return "";
+ }
+ if (hasStringValue()) {
+ return (String) value;
+ }
+
+ ChildNode firstChild = ((ChildNode) value);
+
+ String data = null;
+ if (firstChild.getNodeType() == Node.ENTITY_REFERENCE_NODE){
+ data = ((EntityReferenceImpl)firstChild).getEntityRefValue();
+ }
+ else {
+ data = firstChild.getNodeValue();
+ }
+
+ ChildNode node = firstChild.nextSibling;
+
+ if (node == null || data == null) return (data == null)?"":data;
+
+ StringBuffer value = new StringBuffer(data);
+ while (node != null) {
+ if (node.getNodeType() == Node.ENTITY_REFERENCE_NODE){
+ data = ((EntityReferenceImpl)node).getEntityRefValue();
+ if (data == null) return "";
+ value.append(data);
+ }
+ else {
+ value.append(node.getNodeValue());
+ }
+ node = node.nextSibling;
+ }
+ return value.toString();
+
+ } // getValue():String
+
+
+ /**
+ * The "specified" flag is true if and only if this attribute's
+ * value was explicitly specified in the original document. Note that
+ * the implementation, not the user, is in charge of this
+ * property. If the user asserts an Attribute value (even if it ends
+ * up having the same value as the default), it is considered a
+ * specified attribute. If you really want to revert to the default,
+ * delete the attribute from the Element, and the Implementation will
+ * re-assert the default (if any) in its place, with the appropriate
+ * specified=false setting.
+ */
+ public boolean getSpecified() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return isSpecified();
+
+ } // getSpecified():boolean
+
+ //
+ // Attr2 methods
+ //
+
+ /**
+ * Returns the element node that this attribute is associated with,
+ * or null if the attribute has not been added to an element.
+ *
+ * @see #getOwnerElement
+ *
+ * @deprecated Previous working draft of DOM Level 2. New method
+ * is getOwnerElement().
+ */
+ public Element getElement() {
+ // if we have an owner, ownerNode is our ownerElement, otherwise it's
+ // our ownerDocument and we don't have an ownerElement
+ return (Element) (isOwned() ? ownerNode : null);
+ }
+
+ /**
+ * Returns the element node that this attribute is associated with,
+ * or null if the attribute has not been added to an element.
+ *
+ * @since WD-DOM-Level-2-19990719
+ */
+ public Element getOwnerElement() {
+ // if we have an owner, ownerNode is our ownerElement, otherwise it's
+ // our ownerDocument and we don't have an ownerElement
+ return (Element) (isOwned() ? ownerNode : null);
+ }
+
+ public void normalize() {
+
+ // No need to normalize if already normalized or
+ // if value is kept as a String.
+ if (isNormalized() || hasStringValue())
+ return;
+
+ Node kid, next;
+ ChildNode firstChild = (ChildNode)value;
+ for (kid = firstChild; kid != null; kid = next) {
+ next = kid.getNextSibling();
+
+ // If kid is a text node, we need to check for one of two
+ // conditions:
+ // 1) There is an adjacent text node
+ // 2) There is no adjacent text node, but kid is
+ // an empty text node.
+ if ( kid.getNodeType() == Node.TEXT_NODE )
+ {
+ // If an adjacent text node, merge it with kid
+ if ( next!=null && next.getNodeType() == Node.TEXT_NODE )
+ {
+ ((Text)kid).appendData(next.getNodeValue());
+ removeChild( next );
+ next = kid; // Don't advance; there might be another.
+ }
+ else
+ {
+ // If kid is empty, remove it
+ if ( kid.getNodeValue() == null || kid.getNodeValue().length() == 0 ) {
+ removeChild( kid );
+ }
+ }
+ }
+ }
+
+ isNormalized(true);
+ } // normalize()
+
+ //
+ // Public methods
+ //
+
+ /** NON-DOM, for use by parser */
+ public void setSpecified(boolean arg) {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ isSpecified(arg);
+
+ } // setSpecified(boolean)
+
+ /**
+ * NON-DOM: used by the parser
+ * @param type
+ */
+ public void setType (Object type){
+ this.type = type;
+ }
+
+ //
+ // Object methods
+ //
+
+ /** NON-DOM method for debugging convenience */
+ public String toString() {
+ return getName() + "=" + "\"" + getValue() + "\"";
+ }
+
+ /**
+ * Test whether this node has any children. Convenience shorthand
+ * for (Node.getFirstChild()!=null)
+ */
+ public boolean hasChildNodes() {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return value != null;
+ }
+
+ /**
+ * Obtain a NodeList enumerating all children of this node. If there
+ * are none, an (initially) empty NodeList is returned.
+ *
+ * NodeLists are "live"; as children are added/removed the NodeList
+ * will immediately reflect those changes. Also, the NodeList refers
+ * to the actual nodes, so changes to those nodes made via the DOM tree
+ * will be reflected in the NodeList and vice versa.
+ *
+ * In this implementation, Nodes implement the NodeList interface and
+ * provide their own getChildNodes() support. Other DOMs may solve this
+ * differently.
+ */
+ public NodeList getChildNodes() {
+ // JKESS: KNOWN ISSUE HERE
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return this;
+
+ } // getChildNodes():NodeList
+
+ /** The first child of this Node, or null if none. */
+ public Node getFirstChild() {
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ makeChildNode();
+ return (Node) value;
+
+ } // getFirstChild():Node
+
+ /** The last child of this Node, or null if none. */
+ public Node getLastChild() {
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return lastChild();
+
+ } // getLastChild():Node
+
+ final ChildNode lastChild() {
+ // last child is stored as the previous sibling of first child
+ makeChildNode();
+ return value != null ? ((ChildNode) value).previousSibling : null;
+ }
+
+ final void lastChild(ChildNode node) {
+ // store lastChild as previous sibling of first child
+ if (value != null) {
+ ((ChildNode) value).previousSibling = node;
+ }
+ }
+
+ /**
+ * Move one or more node(s) to our list of children. Note that this
+ * implicitly removes them from their previous parent.
+ *
+ * @param newChild The Node to be moved to our subtree. As a
+ * convenience feature, inserting a DocumentNode will instead insert
+ * all its children.
+ *
+ * @param refChild Current child which newChild should be placed
+ * immediately before. If refChild is null, the insertion occurs
+ * after all existing Nodes, like appendChild().
+ *
+ * @return newChild, in its new state (relocated, or emptied in the case of
+ * DocumentNode.)
+ *
+ * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
+ * type that shouldn't be a child of this node, or if newChild is an
+ * ancestor of this node.
+ *
+ * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
+ * different owner document than we do.
+ *
+ * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
+ * this node.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
+ * read-only.
+ */
+ public Node insertBefore(Node newChild, Node refChild)
+ throws DOMException {
+ // Tail-call; optimizer should be able to do good things with.
+ return internalInsertBefore(newChild, refChild, false);
+ } // insertBefore(Node,Node):Node
+
+ /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
+ * to control which mutation events are spawned. This version of the
+ * insertBefore operation allows us to do so. It is not intended
+ * for use by application programs.
+ */
+ Node internalInsertBefore(Node newChild, Node refChild, boolean replace)
+ throws DOMException {
+
+ CoreDocumentImpl ownerDocument = ownerDocument();
+ boolean errorChecking = ownerDocument.errorChecking;
+
+ if (newChild.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
+ // SLOW BUT SAFE: We could insert the whole subtree without
+ // juggling so many next/previous pointers. (Wipe out the
+ // parent's child-list, patch the parent pointers, set the
+ // ends of the list.) But we know some subclasses have special-
+ // case behavior they add to insertBefore(), so we don't risk it.
+ // This approch also takes fewer bytecodes.
+
+ // NOTE: If one of the children is not a legal child of this
+ // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children
+ // have been transferred. (Alternative behaviors would be to
+ // reparent up to the first failure point or reparent all those
+ // which are acceptable to the target node, neither of which is
+ // as robust. PR-DOM-0818 isn't entirely clear on which it
+ // recommends?????
+
+ // No need to check kids for right-document; if they weren't,
+ // they wouldn't be kids of that DocFrag.
+ if (errorChecking) {
+ for (Node kid = newChild.getFirstChild(); // Prescan
+ kid != null; kid = kid.getNextSibling()) {
+
+ if (!ownerDocument.isKidOK(this, kid)) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null);
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, msg);
+ }
+ }
+ }
+
+ while (newChild.hasChildNodes()) {
+ insertBefore(newChild.getFirstChild(), refChild);
+ }
+ return newChild;
+ }
+
+ if (newChild == refChild) {
+ // stupid case that must be handled as a no-op triggering events...
+ refChild = refChild.getNextSibling();
+ removeChild(newChild);
+ insertBefore(newChild, refChild);
+ return newChild;
+ }
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+
+ if (errorChecking) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+ if (newChild.getOwnerDocument() != ownerDocument) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+ }
+ if (!ownerDocument.isKidOK(this, newChild)) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null);
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, msg);
+ }
+ // refChild must be a child of this node (or null)
+ if (refChild != null && refChild.getParentNode() != this) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+
+ // Prevent cycles in the tree
+ // newChild cannot be ancestor of this Node,
+ // and actually cannot be this
+ boolean treeSafe = true;
+ for (NodeImpl a = this; treeSafe && a != null; a = a.parentNode())
+ {
+ treeSafe = newChild != a;
+ }
+ if (!treeSafe) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null);
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, msg);
+ }
+ }
+
+ makeChildNode(); // make sure we have a node and not a string
+
+ // notify document
+ ownerDocument.insertingNode(this, replace);
+
+ // Convert to internal type, to avoid repeated casting
+ ChildNode newInternal = (ChildNode)newChild;
+
+ Node oldparent = newInternal.parentNode();
+ if (oldparent != null) {
+ oldparent.removeChild(newInternal);
+ }
+
+ // Convert to internal type, to avoid repeated casting
+ ChildNode refInternal = (ChildNode) refChild;
+
+ // Attach up
+ newInternal.ownerNode = this;
+ newInternal.isOwned(true);
+
+ // Attach before and after
+ // Note: firstChild.previousSibling == lastChild!!
+ ChildNode firstChild = (ChildNode) value;
+ if (firstChild == null) {
+ // this our first and only child
+ value = newInternal; // firstchild = newInternal;
+ newInternal.isFirstChild(true);
+ newInternal.previousSibling = newInternal;
+ }
+ else {
+ if (refInternal == null) {
+ // this is an append
+ ChildNode lastChild = firstChild.previousSibling;
+ lastChild.nextSibling = newInternal;
+ newInternal.previousSibling = lastChild;
+ firstChild.previousSibling = newInternal;
+ }
+ else {
+ // this is an insert
+ if (refChild == firstChild) {
+ // at the head of the list
+ firstChild.isFirstChild(false);
+ newInternal.nextSibling = firstChild;
+ newInternal.previousSibling = firstChild.previousSibling;
+ firstChild.previousSibling = newInternal;
+ value = newInternal; // firstChild = newInternal;
+ newInternal.isFirstChild(true);
+ }
+ else {
+ // somewhere in the middle
+ ChildNode prev = refInternal.previousSibling;
+ newInternal.nextSibling = refInternal;
+ prev.nextSibling = newInternal;
+ refInternal.previousSibling = newInternal;
+ newInternal.previousSibling = prev;
+ }
+ }
+ }
+
+ changed();
+
+ // notify document
+ ownerDocument.insertedNode(this, newInternal, replace);
+
+ checkNormalizationAfterInsert(newInternal);
+
+ return newChild;
+
+ } // internalInsertBefore(Node,Node,int):Node
+
+ /**
+ * Remove a child from this Node. The removed child's subtree
+ * remains intact so it may be re-inserted elsewhere.
+ *
+ * @return oldChild, in its new state (removed).
+ *
+ * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
+ * this node.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
+ * read-only.
+ */
+ public Node removeChild(Node oldChild)
+ throws DOMException {
+ // Tail-call, should be optimizable
+ if (hasStringValue()) {
+ // we don't have any child per say so it can't be one of them!
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+ return internalRemoveChild(oldChild, false);
+ } // removeChild(Node) :Node
+
+ /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
+ * to control which mutation events are spawned. This version of the
+ * removeChild operation allows us to do so. It is not intended
+ * for use by application programs.
+ */
+ Node internalRemoveChild(Node oldChild, boolean replace)
+ throws DOMException {
+
+ CoreDocumentImpl ownerDocument = ownerDocument();
+ if (ownerDocument.errorChecking) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+ if (oldChild != null && oldChild.getParentNode() != this) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+ }
+
+ ChildNode oldInternal = (ChildNode) oldChild;
+
+ // notify document
+ ownerDocument.removingNode(this, oldInternal, replace);
+
+ // Patch linked list around oldChild
+ // Note: lastChild == firstChild.previousSibling
+ if (oldInternal == value) { // oldInternal == firstChild
+ // removing first child
+ oldInternal.isFirstChild(false);
+ // next line is: firstChild = oldInternal.nextSibling
+ value = oldInternal.nextSibling;
+ ChildNode firstChild = (ChildNode) value;
+ if (firstChild != null) {
+ firstChild.isFirstChild(true);
+ firstChild.previousSibling = oldInternal.previousSibling;
+ }
+ } else {
+ ChildNode prev = oldInternal.previousSibling;
+ ChildNode next = oldInternal.nextSibling;
+ prev.nextSibling = next;
+ if (next == null) {
+ // removing last child
+ ChildNode firstChild = (ChildNode) value;
+ firstChild.previousSibling = prev;
+ } else {
+ // removing some other child in the middle
+ next.previousSibling = prev;
+ }
+ }
+
+ // Save previous sibling for normalization checking.
+ ChildNode oldPreviousSibling = oldInternal.previousSibling();
+
+ // Remove oldInternal's references to tree
+ oldInternal.ownerNode = ownerDocument;
+ oldInternal.isOwned(false);
+ oldInternal.nextSibling = null;
+ oldInternal.previousSibling = null;
+
+ changed();
+
+ // notify document
+ ownerDocument.removedNode(this, replace);
+
+ checkNormalizationAfterRemove(oldPreviousSibling);
+
+ return oldInternal;
+
+ } // internalRemoveChild(Node,int):Node
+
+ /**
+ * Make newChild occupy the location that oldChild used to
+ * have. Note that newChild will first be removed from its previous
+ * parent, if any. Equivalent to inserting newChild before oldChild,
+ * then removing oldChild.
+ *
+ * @return oldChild, in its new state (removed).
+ *
+ * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
+ * type that shouldn't be a child of this node, or if newChild is
+ * one of our ancestors.
+ *
+ * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
+ * different owner document than we do.
+ *
+ * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
+ * this node.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
+ * read-only.
+ */
+ public Node replaceChild(Node newChild, Node oldChild)
+ throws DOMException {
+
+ makeChildNode();
+
+ // If Mutation Events are being generated, this operation might
+ // throw aggregate events twice when modifying an Attr -- once
+ // on insertion and once on removal. DOM Level 2 does not specify
+ // this as either desirable or undesirable, but hints that
+ // aggregations should be issued only once per user request.
+
+ // notify document
+ CoreDocumentImpl ownerDocument = ownerDocument();
+ ownerDocument.replacingNode(this);
+
+ internalInsertBefore(newChild, oldChild, true);
+ if (newChild != oldChild) {
+ internalRemoveChild(oldChild, true);
+ }
+
+ // notify document
+ ownerDocument.replacedNode(this);
+
+ return oldChild;
+ }
+
+ //
+ // NodeList methods
+ //
+
+ /**
+ * NodeList method: Count the immediate children of this node
+ * @return int
+ */
+ public int getLength() {
+
+ if (hasStringValue()) {
+ return 1;
+ }
+ ChildNode node = (ChildNode) value;
+ int length = 0;
+ for (; node != null; node = node.nextSibling) {
+ length++;
+ }
+ return length;
+
+ } // getLength():int
+
+ /**
+ * NodeList method: Return the Nth immediate child of this node, or
+ * null if the index is out of bounds.
+ * @return org.w3c.dom.Node
+ * @param index int
+ */
+ public Node item(int index) {
+
+ if (hasStringValue()) {
+ if (index != 0 || value == null) {
+ return null;
+ }
+ else {
+ makeChildNode();
+ return (Node) value;
+ }
+ }
+ if (index < 0) {
+ return null;
+ }
+ ChildNode node = (ChildNode) value;
+ for (int i = 0; i < index && node != null; i++) {
+ node = node.nextSibling;
+ }
+ return node;
+
+ } // item(int):Node
+
+ //
+ // DOM3
+ //
+
+ /**
+ * DOM Level 3 WD- Experimental.
+ * Override inherited behavior from ParentNode to support deep equal.
+ * isEqualNode is always deep on Attr nodes.
+ */
+ public boolean isEqualNode(Node arg) {
+ return super.isEqualNode(arg);
+ }
+
+ /**
+ * Introduced in DOM Level 3.
+ * Checks if a type is derived from another by restriction. See:
+ * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
+ *
+ * @param typeNamespaceArg
+ * The namspace of the ancestor type declaration
+ * @param typeNameArg
+ * The name of the ancestor type declaration
+ * @param derivationMethod
+ * The derivation method
+ *
+ * @return boolean True if the type is derived by restriciton for the
+ * reference type
+ */
+ public boolean isDerivedFrom(String typeNamespaceArg,
+ String typeNameArg,
+ int derivationMethod) {
+
+ return false;
+ }
+
+
+ //
+ // Public methods
+ //
+
+ /**
+ * Override default behavior so that if deep is true, children are also
+ * toggled.
+ * @see Node
+ *
+ * Note: this will not change the state of an EntityReference or its
+ * children, which are always read-only.
+ */
+ public void setReadOnly(boolean readOnly, boolean deep) {
+
+ super.setReadOnly(readOnly, deep);
+
+ if (deep) {
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+
+ if (hasStringValue()) {
+ return;
+ }
+ // Recursively set kids
+ for (ChildNode mykid = (ChildNode) value;
+ mykid != null;
+ mykid = mykid.nextSibling) {
+ if (mykid.getNodeType() != Node.ENTITY_REFERENCE_NODE) {
+ mykid.setReadOnly(readOnly,true);
+ }
+ }
+ }
+ } // setReadOnly(boolean,boolean)
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * Override this method in subclass to hook in efficient
+ * internal data structure.
+ */
+ protected void synchronizeChildren() {
+ // By default just change the flag to avoid calling this method again
+ needsSyncChildren(false);
+ }
+
+ /**
+ * Checks the normalized state of this node after inserting a child.
+ * If the inserted child causes this node to be unnormalized, then this
+ * node is flagged accordingly.
+ * The conditions for changing the normalized state are:
+ *
+ * - The inserted child is a text node and one of its adjacent siblings
+ * is also a text node.
+ *
- The inserted child is is itself unnormalized.
+ *
+ *
+ * @param insertedChild the child node that was inserted into this node
+ *
+ * @throws NullPointerException if the inserted child is null
+ */
+ void checkNormalizationAfterInsert(ChildNode insertedChild) {
+ // See if insertion caused this node to be unnormalized.
+ if (insertedChild.getNodeType() == Node.TEXT_NODE) {
+ ChildNode prev = insertedChild.previousSibling();
+ ChildNode next = insertedChild.nextSibling;
+ // If an adjacent sibling of the new child is a text node,
+ // flag this node as unnormalized.
+ if ((prev != null && prev.getNodeType() == Node.TEXT_NODE) ||
+ (next != null && next.getNodeType() == Node.TEXT_NODE)) {
+ isNormalized(false);
+ }
+ }
+ else {
+ // If the new child is not normalized,
+ // then this node is inherently not normalized.
+ if (!insertedChild.isNormalized()) {
+ isNormalized(false);
+ }
+ }
+ } // checkNormalizationAfterInsert(ChildNode)
+
+ /**
+ * Checks the normalized of this node after removing a child.
+ * If the removed child causes this node to be unnormalized, then this
+ * node is flagged accordingly.
+ * The conditions for changing the normalized state are:
+ *
+ * - The removed child had two adjacent siblings that were text nodes.
+ *
+ *
+ * @param previousSibling the previous sibling of the removed child, or
+ * null
+ */
+ void checkNormalizationAfterRemove(ChildNode previousSibling) {
+ // See if removal caused this node to be unnormalized.
+ // If the adjacent siblings of the removed child were both text nodes,
+ // flag this node as unnormalized.
+ if (previousSibling != null &&
+ previousSibling.getNodeType() == Node.TEXT_NODE) {
+
+ ChildNode next = previousSibling.nextSibling;
+ if (next != null && next.getNodeType() == Node.TEXT_NODE) {
+ isNormalized(false);
+ }
+ }
+ } // checkNormalizationAfterRemove(ChildNode)
+
+ //
+ // Serialization methods
+ //
+
+ /** Serialize object. */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+
+ // synchronize chilren
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ // write object
+ out.defaultWriteObject();
+
+ } // writeObject(ObjectOutputStream)
+
+ /** Deserialize object. */
+ private void readObject(ObjectInputStream ois)
+ throws ClassNotFoundException, IOException {
+
+ // perform default deseralization
+ ois.defaultReadObject();
+
+ // hardset synchildren - so we don't try to sync -
+ // it does not make any sense to try to synchildren when we just
+ // deserialize object.
+ needsSyncChildren(false);
+
+ } // readObject(ObjectInputStream)
+
+
+} // class AttrImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/AttrNSImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/AttrNSImpl.java
new file mode 100644
index 0000000..4582d51
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/AttrNSImpl.java
@@ -0,0 +1,324 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl;
+import org.apache.xerces.xni.NamespaceContext;
+import org.w3c.dom.DOMException;
+
+/**
+ * AttrNSImpl inherits from AttrImpl and adds namespace support.
+ *
+ * The qualified name is the node name, and we store localName which is also
+ * used in all queries. On the other hand we recompute the prefix when
+ * necessary.
+ *
+ * @xerces.internal
+ *
+ * @author Arnaud Le Hors, IBM
+ * @author Andy Clark, IBM
+ * @author Ralf Pfeiffer, IBM
+ * @version $Id$
+ */
+public class AttrNSImpl
+ extends AttrImpl {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -781906615369795414L;
+
+ static final String xmlnsURI = "http://www.w3.org/2000/xmlns/";
+ static final String xmlURI = "http://www.w3.org/XML/1998/namespace";
+
+ //
+ // Data
+ //
+
+ /** DOM2: Namespace URI. */
+ protected String namespaceURI;
+
+ /** DOM2: localName. */
+ protected String localName;
+
+ /*
+ * Default constructor
+ */
+ public AttrNSImpl(){}
+
+ /**
+ * DOM2: Constructor for Namespace implementation.
+ */
+ protected AttrNSImpl(CoreDocumentImpl ownerDocument,
+ String namespaceURI,
+ String qualifiedName) {
+
+ super(ownerDocument, qualifiedName);
+ setName(namespaceURI, qualifiedName);
+ }
+
+ private void setName(String namespaceURI, String qname){
+ CoreDocumentImpl ownerDocument = ownerDocument();
+ String prefix;
+ // DOM Level 3: namespace URI is never empty string.
+ this.namespaceURI = namespaceURI;
+ if (namespaceURI !=null) {
+ this.namespaceURI = (namespaceURI.length() == 0)? null
+ : namespaceURI;
+
+ }
+ int colon1 = qname.indexOf(':');
+ int colon2 = qname.lastIndexOf(':');
+ ownerDocument.checkNamespaceWF(qname, colon1, colon2);
+ if (colon1 < 0) {
+ // there is no prefix
+ localName = qname;
+ if (ownerDocument.errorChecking) {
+ ownerDocument.checkQName(null, localName);
+
+ if (qname.equals("xmlns") && (namespaceURI == null
+ || !namespaceURI.equals(NamespaceContext.XMLNS_URI))
+ || (namespaceURI!=null && namespaceURI.equals(NamespaceContext.XMLNS_URI)
+ && !qname.equals("xmlns"))) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NAMESPACE_ERR",
+ null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ }
+ }
+ else {
+ prefix = qname.substring(0, colon1);
+ localName = qname.substring(colon2+1);
+ ownerDocument.checkQName(prefix, localName);
+ ownerDocument.checkDOMNSErr(prefix, namespaceURI);
+ }
+ }
+
+ // when local name is known
+ public AttrNSImpl(CoreDocumentImpl ownerDocument,
+ String namespaceURI,
+ String qualifiedName,
+ String localName) {
+ super(ownerDocument, qualifiedName);
+
+ this.localName = localName;
+ this.namespaceURI = namespaceURI;
+ }
+
+ // for DeferredAttrImpl
+ protected AttrNSImpl(CoreDocumentImpl ownerDocument,
+ String value) {
+ super(ownerDocument, value);
+ }
+
+ // Support for DOM Level 3 renameNode method.
+ // Note: This only deals with part of the pb. It is expected to be
+ // called after the Attr has been detached for one thing.
+ // CoreDocumentImpl does all the work.
+ void rename(String namespaceURI, String qualifiedName) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ this.name = qualifiedName;
+ setName(namespaceURI, qualifiedName);
+ }
+
+ //
+ // DOM2: Namespace methods
+ //
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * The namespace URI of this node, or null if it is unspecified.
+ *
+ * This is not a computed value that is the result of a namespace lookup
+ * based on an examination of the namespace declarations in scope. It is
+ * merely the namespace URI given at creation time.
+ *
+ * For nodes created with a DOM Level 1 method, such as createElement
+ * from the Document interface, this is null.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public String getNamespaceURI()
+ {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ // REVIST: This code could/should be done at a lower-level, such that
+ // the namespaceURI is set properly upon creation. However, there still
+ // seems to be some DOM spec interpretation grey-area.
+ return namespaceURI;
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * The namespace prefix of this node, or null if it is unspecified.
+ *
+ * For nodes created with a DOM Level 1 method, such as createElement
+ * from the Document interface, this is null.
+ *
+ * @since WD-DOM-Level-2-19990923
+ */
+ public String getPrefix()
+ {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ int index = name.indexOf(':');
+ return index < 0 ? null : name.substring(0, index);
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Note that setting this attribute changes the nodeName attribute, which
+ * holds the qualified name, as well as the tagName and name attributes of
+ * the Element and Attr interfaces, when applicable.
+ *
+ * @param prefix The namespace prefix of this node, or null(empty string) if it is unspecified.
+ *
+ * @exception INVALID_CHARACTER_ERR
+ * Raised if the specified
+ * prefix contains an invalid character.
+ * @exception DOMException
+ * @since WD-DOM-Level-2-19990923
+ */
+ public void setPrefix(String prefix)
+ throws DOMException
+ {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (ownerDocument().errorChecking) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+ if (prefix != null && prefix.length() != 0) {
+
+ if (!CoreDocumentImpl.isXMLName(prefix,ownerDocument().isXML11Version())) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ if (namespaceURI == null || prefix.indexOf(':') >=0) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+
+ }
+ if (prefix.equals("xmlns")) {
+ if (!namespaceURI.equals(xmlnsURI)){
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ } else if (prefix.equals("xml")) {
+ if (!namespaceURI.equals(xmlURI)) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ }else if (name.equals("xmlns")) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ }
+ }
+
+ // update node name with new qualifiedName
+ if (prefix !=null && prefix.length() != 0) {
+ name = prefix + ":" + localName;
+ }
+ else {
+ name = localName;
+ }
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Returns the local part of the qualified name of this node.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public String getLocalName()
+ {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return localName;
+ }
+
+
+ /**
+ * @see org.w3c.dom.TypeInfo#getTypeName()
+ */
+ public String getTypeName() {
+ if (type !=null){
+ if (type instanceof XSSimpleTypeDecl){
+ return ((XSSimpleTypeDecl)type).getName();
+ }
+ return (String)type;
+ }
+ return null;
+ }
+
+ /**
+ * Introduced in DOM Level 3.
+ * Checks if a type is derived from another by restriction. See:
+ * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
+ *
+ * @param typeNamespaceArg
+ * The namspace of the ancestor type declaration
+ * @param typeNameArg
+ * The name of the ancestor type declaration
+ * @param derivationMethod
+ * The derivation method
+ *
+ * @return boolean True if the type is derived by restriciton for the
+ * reference type
+ */
+ public boolean isDerivedFrom(String typeNamespaceArg,
+ String typeNameArg,
+ int derivationMethod) {
+ if (type != null) {
+ if (type instanceof XSSimpleTypeDecl) {
+ return ((XSSimpleTypeDecl) type).isDOMDerivedFrom(
+ typeNamespaceArg, typeNameArg, derivationMethod);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @see org.w3c.dom.TypeInfo#getTypeNamespace()
+ */
+ public String getTypeNamespace() {
+ if (type !=null) {
+ if (type instanceof XSSimpleTypeDecl){
+ return ((XSSimpleTypeDecl)type).getNamespace();
+ }
+ return DTD_URI;
+ }
+ return null;
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/AttributeMap.java b/resources/xerces2-j-src/org/apache/xerces/dom/AttributeMap.java
new file mode 100644
index 0000000..136bf60
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/AttributeMap.java
@@ -0,0 +1,603 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+
+/**
+ * AttributeMap inherits from NamedNodeMapImpl and extends it to deal with the
+ * specifics of storing attributes. These are:
+ *
+ * - managing ownership of attribute nodes
+ *
- managing default attributes
+ *
- firing mutation events
+ *
+ *
+ * This class doesn't directly support mutation events, however, it notifies
+ * the document when mutations are performed so that the document class do so.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class AttributeMap extends NamedNodeMapImpl {
+
+ /** Serialization version. */
+ static final long serialVersionUID = 8872606282138665383L;
+
+ //
+ // Constructors
+ //
+
+ /** Constructs a named node map. */
+ protected AttributeMap(ElementImpl ownerNode, NamedNodeMapImpl defaults) {
+ super(ownerNode);
+ if (defaults != null) {
+ // initialize map with the defaults
+ cloneContent(defaults);
+ if (nodes != null) {
+ hasDefaults(true);
+ }
+ }
+ }
+
+ /**
+ * Adds an attribute using its nodeName attribute.
+ * @see org.w3c.dom.NamedNodeMap#setNamedItem
+ * @return If the new Node replaces an existing node the replaced Node is
+ * returned, otherwise null is returned.
+ * @param arg
+ * An Attr node to store in this map.
+ * @exception org.w3c.dom.DOMException The exception description.
+ */
+ public Node setNamedItem(Node arg)
+ throws DOMException {
+
+ boolean errCheck = ownerNode.ownerDocument().errorChecking;
+ if (errCheck) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+ if (arg.getOwnerDocument() != ownerNode.ownerDocument()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+ }
+ if (arg.getNodeType() != Node.ATTRIBUTE_NODE) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null);
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, msg);
+ }
+ }
+ AttrImpl argn = (AttrImpl)arg;
+
+ if (argn.isOwned()){
+ if (errCheck && argn.getOwnerElement() != ownerNode) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INUSE_ATTRIBUTE_ERR", null);
+ throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, msg);
+ }
+ // replacing an Attribute with itself does nothing
+ return arg;
+ }
+
+
+ // set owner
+ argn.ownerNode = ownerNode;
+ argn.isOwned(true);
+
+ int i = findNamePoint(argn.getNodeName(),0);
+ AttrImpl previous = null;
+ if (i >= 0) {
+ previous = (AttrImpl) nodes.get(i);
+ nodes.set(i, arg);
+ previous.ownerNode = ownerNode.ownerDocument();
+ previous.isOwned(false);
+ // make sure it won't be mistaken with defaults in case it's reused
+ previous.isSpecified(true);
+ } else {
+ i = -1 - i; // Insert point (may be end of list)
+ if (null == nodes) {
+ nodes = new ArrayList(5);
+ }
+ nodes.add(i, arg);
+ }
+
+ // notify document
+ ownerNode.ownerDocument().setAttrNode(argn, previous);
+
+ // If the new attribute is not normalized,
+ // the owning element is inherently not normalized.
+ if (!argn.isNormalized()) {
+ ownerNode.isNormalized(false);
+ }
+ return previous;
+
+ } // setNamedItem(Node):Node
+
+ /**
+ * Adds an attribute using its namespaceURI and localName.
+ * @see org.w3c.dom.NamedNodeMap#setNamedItem
+ * @return If the new Node replaces an existing node the replaced Node is
+ * returned, otherwise null is returned.
+ * @param arg A node to store in a named node map.
+ */
+ public Node setNamedItemNS(Node arg)
+ throws DOMException {
+
+ boolean errCheck = ownerNode.ownerDocument().errorChecking;
+ if (errCheck) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+ if(arg.getOwnerDocument() != ownerNode.ownerDocument()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+ }
+ if (arg.getNodeType() != Node.ATTRIBUTE_NODE) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null);
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, msg);
+ }
+ }
+ AttrImpl argn = (AttrImpl)arg;
+
+ if (argn.isOwned()){
+ if (errCheck && argn.getOwnerElement() != ownerNode) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INUSE_ATTRIBUTE_ERR", null);
+ throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, msg);
+ }
+ // replacing an Attribute with itself does nothing
+ return arg;
+ }
+
+ // set owner
+ argn.ownerNode = ownerNode;
+ argn.isOwned(true);
+
+ int i = findNamePoint(argn.getNamespaceURI(), argn.getLocalName());
+ AttrImpl previous = null;
+ if (i >= 0) {
+ previous = (AttrImpl) nodes.get(i);
+ nodes.set(i, arg);
+ previous.ownerNode = ownerNode.ownerDocument();
+ previous.isOwned(false);
+ // make sure it won't be mistaken with defaults in case it's reused
+ previous.isSpecified(true);
+ } else {
+ // If we can't find by namespaceURI, localName, then we find by
+ // nodeName so we know where to insert.
+ i = findNamePoint(arg.getNodeName(),0);
+ if (i >=0) {
+ previous = (AttrImpl) nodes.get(i);
+ nodes.add(i, arg);
+ } else {
+ i = -1 - i; // Insert point (may be end of list)
+ if (null == nodes) {
+ nodes = new ArrayList(5);
+ }
+ nodes.add(i, arg);
+ }
+ }
+ // changed(true);
+
+ // notify document
+ ownerNode.ownerDocument().setAttrNode(argn, previous);
+
+ // If the new attribute is not normalized,
+ // the owning element is inherently not normalized.
+ if (!argn.isNormalized()) {
+ ownerNode.isNormalized(false);
+ }
+ return previous;
+
+ } // setNamedItemNS(Node):Node
+
+ /**
+ * Removes an attribute specified by name.
+ * @param name
+ * The name of a node to remove. If the
+ * removed attribute is known to have a default value, an
+ * attribute immediately appears containing the default value
+ * as well as the corresponding namespace URI, local name,
+ * and prefix when applicable.
+ * @return The node removed from the map if a node with such a name exists.
+ * @throws NOT_FOUND_ERR: Raised if there is no node named
+ * name in the map.
+ */
+ /***/
+ public Node removeNamedItem(String name)
+ throws DOMException {
+ return internalRemoveNamedItem(name, true);
+ }
+
+ /**
+ * Same as removeNamedItem except that it simply returns null if the
+ * specified name is not found.
+ */
+ Node safeRemoveNamedItem(String name) {
+ return internalRemoveNamedItem(name, false);
+ }
+
+
+ /**
+ * NON-DOM: Remove the node object
+ *
+ * NOTE: Specifically removes THIS NODE -- not the node with this
+ * name, nor the node with these contents. If node does not belong to
+ * this named node map, we throw a DOMException.
+ *
+ * @param item The node to remove
+ * @param addDefault true -- magically add default attribute
+ * @return Removed node
+ * @exception DOMException
+ */
+ protected Node removeItem(Node item, boolean addDefault)
+ throws DOMException {
+
+ int index = -1;
+ if (nodes != null) {
+ final int size = nodes.size();
+ for (int i = 0; i < size; ++i) {
+ if (nodes.get(i) == item) {
+ index = i;
+ break;
+ }
+ }
+ }
+ if (index < 0) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+
+ return remove((AttrImpl)item, index, addDefault);
+ }
+
+ /**
+ * Internal removeNamedItem method allowing to specify whether an exception
+ * must be thrown if the specified name is not found.
+ */
+ final protected Node internalRemoveNamedItem(String name, boolean raiseEx){
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+ int i = findNamePoint(name,0);
+ if (i < 0) {
+ if (raiseEx) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ } else {
+ return null;
+ }
+ }
+
+ return remove((AttrImpl)nodes.get(i), i, true);
+
+ } // internalRemoveNamedItem(String,boolean):Node
+
+ private final Node remove(AttrImpl attr, int index,
+ boolean addDefault) {
+
+ CoreDocumentImpl ownerDocument = ownerNode.ownerDocument();
+ String name = attr.getNodeName();
+ if (attr.isIdAttribute()) {
+ ownerDocument.removeIdentifier(attr.getValue());
+ }
+
+ if (hasDefaults() && addDefault) {
+ // If there's a default, add it instead
+ NamedNodeMapImpl defaults =
+ ((ElementImpl) ownerNode).getDefaultAttributes();
+
+ Node d;
+ if (defaults != null &&
+ (d = defaults.getNamedItem(name)) != null &&
+ findNamePoint(name, index+1) < 0) {
+ NodeImpl clone = (NodeImpl)d.cloneNode(true);
+ if (d.getLocalName() !=null){
+ // we must rely on the name to find a default attribute
+ // ("test:attr"), but while copying it from the DOCTYPE
+ // we should not loose namespace URI that was assigned
+ // to the attribute in the instance document.
+ ((AttrNSImpl)clone).namespaceURI = attr.getNamespaceURI();
+ }
+ clone.ownerNode = ownerNode;
+ clone.isOwned(true);
+ clone.isSpecified(false);
+
+ nodes.set(index, clone);
+ if (attr.isIdAttribute()) {
+ ownerDocument.putIdentifier(clone.getNodeValue(),
+ (ElementImpl)ownerNode);
+ }
+ } else {
+ nodes.remove(index);
+ }
+ } else {
+ nodes.remove(index);
+ }
+
+ // changed(true);
+
+ // remove reference to owner
+ attr.ownerNode = ownerDocument;
+ attr.isOwned(false);
+
+ // make sure it won't be mistaken with defaults in case it's
+ // reused
+ attr.isSpecified(true);
+ attr.isIdAttribute(false);
+
+ // notify document
+ ownerDocument.removedAttrNode(attr, ownerNode, name);
+
+ return attr;
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ * Removes an attribute specified by local name and namespace URI.
+ * @param namespaceURI
+ * The namespace URI of the node to remove.
+ * When it is null or an empty string, this
+ * method behaves like removeNamedItem.
+ * @param name The local name of the node to remove. If the
+ * removed attribute is known to have a default
+ * value, an attribute immediately appears
+ * containing the default value.
+ * @return Node The node removed from the map if a node with such
+ * a local name and namespace URI exists.
+ * @throws NOT_FOUND_ERR: Raised if there is no node named
+ * name in the map.
+ */
+ public Node removeNamedItemNS(String namespaceURI, String name)
+ throws DOMException {
+ return internalRemoveNamedItemNS(namespaceURI, name, true);
+ }
+
+ /**
+ * Same as removeNamedItem except that it simply returns null if the
+ * specified local name and namespace URI is not found.
+ */
+ Node safeRemoveNamedItemNS(String namespaceURI, String name) {
+ return internalRemoveNamedItemNS(namespaceURI, name, false);
+ }
+
+ /**
+ * Internal removeNamedItemNS method allowing to specify whether an
+ * exception must be thrown if the specified local name and namespace URI
+ * is not found.
+ */
+ final protected Node internalRemoveNamedItemNS(String namespaceURI,
+ String name,
+ boolean raiseEx) {
+
+ CoreDocumentImpl ownerDocument = ownerNode.ownerDocument();
+ if (ownerDocument.errorChecking && isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+ int i = findNamePoint(namespaceURI, name);
+ if (i < 0) {
+ if (raiseEx) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ } else {
+ return null;
+ }
+ }
+
+ AttrImpl n = (AttrImpl)nodes.get(i);
+
+ if (n.isIdAttribute()) {
+ ownerDocument.removeIdentifier(n.getValue());
+ }
+ // If there's a default, add it instead
+ String nodeName = n.getNodeName();
+ if (hasDefaults()) {
+ NamedNodeMapImpl defaults = ((ElementImpl) ownerNode).getDefaultAttributes();
+ Node d;
+ if (defaults != null
+ && (d = defaults.getNamedItem(nodeName)) != null)
+ {
+ int j = findNamePoint(nodeName,0);
+ if (j>=0 && findNamePoint(nodeName, j+1) < 0) {
+ NodeImpl clone = (NodeImpl)d.cloneNode(true);
+ clone.ownerNode = ownerNode;
+ if (d.getLocalName() != null) {
+ // we must rely on the name to find a default attribute
+ // ("test:attr"), but while copying it from the DOCTYPE
+ // we should not loose namespace URI that was assigned
+ // to the attribute in the instance document.
+ ((AttrNSImpl)clone).namespaceURI = namespaceURI;
+ }
+ clone.isOwned(true);
+ clone.isSpecified(false);
+ nodes.set(i, clone);
+ if (clone.isIdAttribute()) {
+ ownerDocument.putIdentifier(clone.getNodeValue(),
+ (ElementImpl)ownerNode);
+ }
+ } else {
+ nodes.remove(i);
+ }
+ } else {
+ nodes.remove(i);
+ }
+ } else {
+ nodes.remove(i);
+ }
+
+ // changed(true);
+
+ // remove reference to owner
+ n.ownerNode = ownerDocument;
+ n.isOwned(false);
+ // make sure it won't be mistaken with defaults in case it's
+ // reused
+ n.isSpecified(true);
+ // update id table if needed
+ n.isIdAttribute(false);
+
+ // notify document
+ ownerDocument.removedAttrNode(n, ownerNode, name);
+
+ return n;
+
+ } // internalRemoveNamedItemNS(String,String,boolean):Node
+
+ //
+ // Public methods
+ //
+
+ /**
+ * Cloning a NamedNodeMap is a DEEP OPERATION; it always clones
+ * all the nodes contained in the map.
+ */
+
+ public NamedNodeMapImpl cloneMap(NodeImpl ownerNode) {
+ AttributeMap newmap =
+ new AttributeMap((ElementImpl) ownerNode, null);
+ newmap.hasDefaults(hasDefaults());
+ newmap.cloneContent(this);
+ return newmap;
+ } // cloneMap():AttributeMap
+
+ /**
+ * Override parent's method to set the ownerNode correctly
+ */
+ protected void cloneContent(NamedNodeMapImpl srcmap) {
+ List srcnodes = srcmap.nodes;
+ if (srcnodes != null) {
+ int size = srcnodes.size();
+ if (size != 0) {
+ if (nodes == null) {
+ nodes = new ArrayList(size);
+ }
+ else {
+ nodes.clear();
+ }
+ for (int i = 0; i < size; ++i) {
+ NodeImpl n = (NodeImpl) srcnodes.get(i);
+ NodeImpl clone = (NodeImpl) n.cloneNode(true);
+ clone.isSpecified(n.isSpecified());
+ nodes.add(clone);
+ clone.ownerNode = ownerNode;
+ clone.isOwned(true);
+ }
+ }
+ }
+ } // cloneContent():AttributeMap
+
+
+ /**
+ * Move specified attributes from the given map to this one
+ */
+ void moveSpecifiedAttributes(AttributeMap srcmap) {
+ int nsize = (srcmap.nodes != null) ? srcmap.nodes.size() : 0;
+ for (int i = nsize - 1; i >= 0; i--) {
+ AttrImpl attr = (AttrImpl) srcmap.nodes.get(i);
+ if (attr.isSpecified()) {
+ srcmap.remove(attr, i, false);
+ if (attr.getLocalName() != null) {
+ setNamedItem(attr);
+ }
+ else {
+ setNamedItemNS(attr);
+ }
+ }
+ }
+ } // moveSpecifiedAttributes(AttributeMap):void
+
+
+ /**
+ * Get this AttributeMap in sync with the given "defaults" map.
+ * @param defaults The default attributes map to sync with.
+ */
+ protected void reconcileDefaults(NamedNodeMapImpl defaults) {
+
+ // remove any existing default
+ int nsize = (nodes != null) ? nodes.size() : 0;
+ for (int i = nsize - 1; i >= 0; --i) {
+ AttrImpl attr = (AttrImpl) nodes.get(i);
+ if (!attr.isSpecified()) {
+ remove(attr, i, false);
+ }
+ }
+ // add the new defaults
+ if (defaults == null) {
+ return;
+ }
+ if (nodes == null || nodes.size() == 0) {
+ cloneContent(defaults);
+ }
+ else {
+ int dsize = defaults.nodes.size();
+ for (int n = 0; n < dsize; ++n) {
+ AttrImpl d = (AttrImpl) defaults.nodes.get(n);
+ int i = findNamePoint(d.getNodeName(), 0);
+ if (i < 0) {
+ i = -1 - i;
+ NodeImpl clone = (NodeImpl) d.cloneNode(true);
+ clone.ownerNode = ownerNode;
+ clone.isOwned(true);
+ clone.isSpecified(false);
+ nodes.add(i, clone);
+ }
+ }
+ }
+
+ } // reconcileDefaults()
+
+ protected final int addItem (Node arg) {
+
+ final AttrImpl argn = (AttrImpl) arg;
+
+ // set owner
+ argn.ownerNode = ownerNode;
+ argn.isOwned(true);
+
+ int i = findNamePoint(argn.getNamespaceURI(), argn.getLocalName());
+ if (i >= 0) {
+ nodes.set(i, arg);
+ }
+ else {
+ // If we can't find by namespaceURI, localName, then we find by
+ // nodeName so we know where to insert.
+ i = findNamePoint(argn.getNodeName(),0);
+ if (i >= 0) {
+ nodes.add(i, arg);
+ }
+ else {
+ i = -1 - i; // Insert point (may be end of list)
+ if (null == nodes) {
+ nodes = new ArrayList(5);
+ }
+ nodes.add(i, arg);
+ }
+ }
+
+ // notify document
+ ownerNode.ownerDocument().setAttrNode(argn, null);
+ return i;
+ }
+
+} // class AttributeMap
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/CDATASectionImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/CDATASectionImpl.java
new file mode 100644
index 0000000..514f948
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/CDATASectionImpl.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Node;
+
+/**
+ * XML provides the CDATA markup to allow a region of text in which
+ * most of the XML delimiter recognition does not take place. This is
+ * intended to ease the task of quoting XML fragments and other
+ * programmatic information in a document's text without needing to
+ * escape these special characters. It's primarily a convenience feature
+ * for those who are hand-editing XML.
+ *
+ * CDATASection is an Extended DOM feature, and is not used in HTML
+ * contexts.
+ *
+ * Within the DOM, CDATASections are treated essentially as Text
+ * blocks. Their distinct type is retained in order to allow us to
+ * properly recreate the XML syntax when we write them out.
+ *
+ * Reminder: CDATA IS NOT A COMPLETELY GENERAL SOLUTION; it can't
+ * quote its own end-of-block marking. If you need to write out a
+ * CDATA that contains the ]]> sequence, it's your responsibility to
+ * split that string over two successive CDATAs at that time.
+ *
+ * CDATA does not participate in Element.normalize() processing.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class CDATASectionImpl
+ extends TextImpl
+ implements CDATASection {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 2372071297878177780L;
+
+ //
+ // Constructors
+ //
+
+ /** Factory constructor for creating a CDATA section. */
+ public CDATASectionImpl(CoreDocumentImpl ownerDoc, String data) {
+ super(ownerDoc, data);
+ }
+
+ //
+ // Node methods
+ //
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public short getNodeType() {
+ return Node.CDATA_SECTION_NODE;
+ }
+
+ /** Returns the node name. */
+ public String getNodeName() {
+ return "#cdata-section";
+ }
+
+} // class CDATASectionImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/CharacterDataImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/CharacterDataImpl.java
new file mode 100644
index 0000000..eb02ac3
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/CharacterDataImpl.java
@@ -0,0 +1,423 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * CharacterData is an abstract Node that can carry character data as its
+ * Value. It provides shared behavior for Text, CData, and
+ * possibly other node types. All offsets are 0-based.
+ *
+ * Since ProcessingInstructionImpl inherits from this class to reuse the
+ * setNodeValue method, this class isn't declared as implementing the interface
+ * CharacterData. This is done by relevant subclasses (TexImpl, CommentImpl).
+ *
+ * This class doesn't directly support mutation events, however, it notifies
+ * the document when mutations are performed so that the document class do so.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public abstract class CharacterDataImpl
+ extends ChildNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 7931170150428474230L;
+
+ //
+ // Data
+ //
+
+ protected String data;
+
+ /** Empty child nodes. */
+ private static final transient NodeList singletonNodeList = new NodeList() {
+ public Node item(int index) { return null; }
+ public int getLength() { return 0; }
+ };
+
+ //
+ // Constructors
+ //
+
+ public CharacterDataImpl(){}
+
+ /** Factory constructor. */
+ protected CharacterDataImpl(CoreDocumentImpl ownerDocument, String data) {
+ super(ownerDocument);
+ this.data = data;
+ }
+
+ //
+ // Node methods
+ //
+
+ /** Returns an empty node list. */
+ public NodeList getChildNodes() {
+ return singletonNodeList;
+ }
+
+ /*
+ * returns the content of this node
+ */
+ public String getNodeValue() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return data;
+ }
+
+ /** Convenience wrapper for calling setNodeValueInternal when
+ * we are not performing a replacement operation
+ */
+ protected void setNodeValueInternal (String value) {
+ setNodeValueInternal(value, false);
+ }
+
+ /** This function added so that we can distinguish whether
+ * setNodeValue has been called from some other DOM functions.
+ * or by the client.
+ * This is important, because we do one type of Range fix-up,
+ * from the high-level functions in CharacterData, and another
+ * type if the client simply calls setNodeValue(value).
+ */
+ protected void setNodeValueInternal(String value, boolean replace) {
+
+ CoreDocumentImpl ownerDocument = ownerDocument();
+
+ if (ownerDocument.errorChecking && isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+
+ // revisit: may want to set the value in ownerDocument.
+ // Default behavior, overridden in some subclasses
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ // keep old value for document notification
+ String oldvalue = this.data;
+
+ // notify document
+ ownerDocument.modifyingCharacterData(this, replace);
+
+ this.data = value;
+
+ // notify document
+ ownerDocument.modifiedCharacterData(this, oldvalue, value, replace);
+ }
+
+ /**
+ * Sets the content, possibly firing related events,
+ * and updating ranges (via notification to the document)
+ */
+ public void setNodeValue(String value) {
+
+ setNodeValueInternal(value);
+
+ // notify document
+ ownerDocument().replacedText(this);
+ }
+
+ //
+ // CharacterData methods
+ //
+
+ /**
+ * Retrieve character data currently stored in this node.
+ *
+ * @throws DOMExcpetion(DOMSTRING_SIZE_ERR) In some implementations,
+ * the stored data may exceed the permitted length of strings. If so,
+ * getData() will throw this DOMException advising the user to
+ * instead retrieve the data in chunks via the substring() operation.
+ */
+ public String getData() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return data;
+ }
+
+ /**
+ * Report number of characters currently stored in this node's
+ * data. It may be 0, meaning that the value is an empty string.
+ */
+ public int getLength() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return data.length();
+ }
+
+ /**
+ * Concatenate additional characters onto the end of the data
+ * stored in this node. Note that this, and insert(), are the paths
+ * by which a DOM could wind up accumulating more data than the
+ * language's strings can easily handle. (See above discussion.)
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is readonly.
+ */
+ public void appendData(String data) {
+
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+ if (data == null) {
+ return;
+ }
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ setNodeValue(this.data + data);
+
+ } // appendData(String)
+
+ /**
+ * Remove a range of characters from the node's value. Throws a
+ * DOMException if the offset is beyond the end of the
+ * string. However, a deletion _count_ that exceeds the available
+ * data is accepted as a delete-to-end request.
+ *
+ * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
+ * greater than length, or if count is negative.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is
+ * readonly.
+ */
+ public void deleteData(int offset, int count)
+ throws DOMException {
+
+ internalDeleteData(offset, count, false);
+ } // deleteData(int,int)
+
+
+ /** NON-DOM INTERNAL: Within DOM actions, we sometimes need to be able
+ * to control which mutation events are spawned. This version of the
+ * deleteData operation allows us to do so. It is not intended
+ * for use by application programs.
+ */
+ void internalDeleteData (int offset, int count, boolean replace)
+ throws DOMException {
+
+ CoreDocumentImpl ownerDocument = ownerDocument();
+ if (ownerDocument.errorChecking) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+
+ if (count < 0) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null);
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
+ }
+ }
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ int tailLength = Math.max(data.length() - count - offset, 0);
+ try {
+ String value = data.substring(0, offset) +
+ (tailLength > 0 ? data.substring(offset + count, offset + count + tailLength) : "");
+
+ setNodeValueInternal(value, replace);
+
+ // notify document
+ ownerDocument.deletedText(this, offset, count);
+ }
+ catch (StringIndexOutOfBoundsException e) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null);
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
+ }
+
+ } // internalDeleteData(int,int,boolean)
+
+ /**
+ * Insert additional characters into the data stored in this node,
+ * at the offset specified.
+ *
+ * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
+ * greater than length.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is readonly.
+ */
+ public void insertData(int offset, String data)
+ throws DOMException {
+
+ internalInsertData(offset, data, false);
+
+ } // insertData(int,int)
+
+
+
+ /** NON-DOM INTERNAL: Within DOM actions, we sometimes need to be able
+ * to control which mutation events are spawned. This version of the
+ * insertData operation allows us to do so. It is not intended
+ * for use by application programs.
+ */
+ void internalInsertData (int offset, String data, boolean replace)
+ throws DOMException {
+
+ CoreDocumentImpl ownerDocument = ownerDocument();
+
+ if (ownerDocument.errorChecking && isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ try {
+ String value =
+ new StringBuffer(this.data).insert(offset, data).toString();
+
+
+ setNodeValueInternal(value, replace);
+
+ // notify document
+ ownerDocument.insertedText(this, offset, data.length());
+ }
+ catch (StringIndexOutOfBoundsException e) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null);
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
+ }
+
+ } // internalInsertData(int,String,boolean)
+
+
+
+ /**
+ * Replace a series of characters at the specified (zero-based)
+ * offset with a new string, NOT necessarily of the same
+ * length. Convenience method, equivalent to a delete followed by an
+ * insert. Throws a DOMException if the specified offset is beyond
+ * the end of the existing data.
+ *
+ * @param offset The offset at which to begin replacing.
+ *
+ * @param count The number of characters to remove,
+ * interpreted as in the delete() method.
+ *
+ * @param data The new string to be inserted at offset in place of
+ * the removed data. Note that the entire string will
+ * be inserted -- the count parameter does not affect
+ * insertion, and the new data may be longer or shorter
+ * than the substring it replaces.
+ *
+ * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
+ * greater than length, or if count is negative.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is
+ * readonly.
+ */
+ public void replaceData(int offset, int count, String data)
+ throws DOMException {
+
+ CoreDocumentImpl ownerDocument = ownerDocument();
+
+ // The read-only check is done by deleteData()
+ // ***** This could be more efficient w/r/t Mutation Events,
+ // specifically by aggregating DOMAttrModified and
+ // DOMSubtreeModified. But mutation events are
+ // underspecified; I don't feel compelled
+ // to deal with it right now.
+ if (ownerDocument.errorChecking && isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ //notify document
+ ownerDocument.replacingData(this);
+
+ // keep old value for document notification
+ String oldvalue = this.data;
+
+ internalDeleteData(offset, count, true);
+ internalInsertData(offset, data, true);
+
+ ownerDocument.replacedCharacterData(this, oldvalue, this.data);
+
+ } // replaceData(int,int,String)
+
+ /**
+ * Store character data into this node.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if node is readonly.
+ */
+ public void setData(String value)
+ throws DOMException {
+ setNodeValue(value);
+ }
+
+ /**
+ * Substring is more than a convenience function. In some
+ * implementations of the DOM, where the stored data may exceed the
+ * length that can be returned in a single string, the only way to
+ * read it all is to extract it in chunks via this method.
+ *
+ * @param offset Zero-based offset of first character to retrieve.
+ * @param count Number of characters to retrieve.
+ *
+ * If the sum of offset and count exceeds the length, all characters
+ * to end of data are returned.
+ *
+ * @throws DOMException(INDEX_SIZE_ERR) if offset is negative or
+ * greater than length, or if count is negative.
+ *
+ * @throws DOMException(WSTRING_SIZE_ERR) In some implementations,
+ * count may exceed the permitted length of strings. If so,
+ * substring() will throw this DOMException advising the user to
+ * instead retrieve the data in smaller chunks.
+ */
+ public String substringData(int offset, int count)
+ throws DOMException {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ int length = data.length();
+ if (count < 0 || offset < 0 || offset > length - 1) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null);
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
+ }
+
+ int tailIndex = Math.min(offset + count, length);
+
+ return data.substring(offset, tailIndex);
+
+ } // substringData(int,int):String
+
+} // class CharacterDataImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/ChildNode.java b/resources/xerces2-j-src/org/apache/xerces/dom/ChildNode.java
new file mode 100644
index 0000000..c9ba429
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/ChildNode.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.Node;
+
+/**
+ * ChildNode inherits from NodeImpl and adds the capability of being a child by
+ * having references to its previous and next siblings.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public abstract class ChildNode
+ extends NodeImpl {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -6112455738802414002L;
+
+ //
+ // Data
+ //
+
+ /** Previous sibling. */
+ protected ChildNode previousSibling;
+
+ /** Next sibling. */
+ protected ChildNode nextSibling;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * No public constructor; only subclasses of Node should be
+ * instantiated, and those normally via a Document's factory methods
+ *
+ * Every Node knows what Document it belongs to.
+ */
+ protected ChildNode(CoreDocumentImpl ownerDocument) {
+ super(ownerDocument);
+ } // (CoreDocumentImpl)
+
+ /** Constructor for serialization. */
+ public ChildNode() {}
+
+ //
+ // Node methods
+ //
+
+ /**
+ * Returns a duplicate of a given node. You can consider this a
+ * generic "copy constructor" for nodes. The newly returned object should
+ * be completely independent of the source object's subtree, so changes
+ * in one after the clone has been made will not affect the other.
+ *
+ * Note: since we never have any children deep is meaningless here,
+ * ParentNode overrides this behavior.
+ * @see ParentNode
+ *
+ *
+ * Example: Cloning a Text node will copy both the node and the text it
+ * contains.
+ *
+ * Example: Cloning something that has children -- Element or Attr, for
+ * example -- will _not_ clone those children unless a "deep clone"
+ * has been requested. A shallow clone of an Attr node will yield an
+ * empty Attr of the same name.
+ *
+ * NOTE: Clones will always be read/write, even if the node being cloned
+ * is read-only, to permit applications using only the DOM API to obtain
+ * editable copies of locked portions of the tree.
+ */
+ public Node cloneNode(boolean deep) {
+
+ ChildNode newnode = (ChildNode) super.cloneNode(deep);
+
+ // Need to break the association w/ original kids
+ newnode.previousSibling = null;
+ newnode.nextSibling = null;
+ newnode.isFirstChild(false);
+
+ return newnode;
+
+ } // cloneNode(boolean):Node
+
+ /**
+ * Returns the parent node of this node
+ */
+ public Node getParentNode() {
+ // if we have an owner, ownerNode is our parent, otherwise it's
+ // our ownerDocument and we don't have a parent
+ return isOwned() ? ownerNode : null;
+ }
+
+ /*
+ * same as above but returns internal type
+ */
+ final NodeImpl parentNode() {
+ // if we have an owner, ownerNode is our parent, otherwise it's
+ // our ownerDocument and we don't have a parent
+ return isOwned() ? ownerNode : null;
+ }
+
+ /** The next child of this node's parent, or null if none */
+ public Node getNextSibling() {
+ return nextSibling;
+ }
+
+ /** The previous child of this node's parent, or null if none */
+ public Node getPreviousSibling() {
+ // if we are the firstChild, previousSibling actually refers to our
+ // parent's lastChild, but we hide that
+ return isFirstChild() ? null : previousSibling;
+ }
+
+ /*
+ * same as above but returns internal type
+ */
+ final ChildNode previousSibling() {
+ // if we are the firstChild, previousSibling actually refers to our
+ // parent's lastChild, but we hide that
+ return isFirstChild() ? null : previousSibling;
+ }
+
+} // class ChildNode
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/CommentImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/CommentImpl.java
new file mode 100644
index 0000000..6bb0d59
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/CommentImpl.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.Comment;
+import org.w3c.dom.Node;
+
+/**
+ * Represents an XML (or HTML) comment.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class CommentImpl
+ extends CharacterDataImpl
+ implements CharacterData, Comment {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -2685736833408134044L;
+
+ //
+ // Constructors
+ //
+
+ /** Factory constructor. */
+ public CommentImpl(CoreDocumentImpl ownerDoc, String data) {
+ super(ownerDoc, data);
+ }
+
+ //
+ // Node methods
+ //
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public short getNodeType() {
+ return Node.COMMENT_NODE;
+ }
+
+ /** Returns the node name. */
+ public String getNodeName() {
+ return "#comment";
+ }
+
+} // class CommentImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/CoreDOMImplementationImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/CoreDOMImplementationImpl.java
new file mode 100644
index 0000000..041db5b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/CoreDOMImplementationImpl.java
@@ -0,0 +1,712 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.xerces.dom;
+
+import java.lang.ref.SoftReference;
+
+import org.apache.xerces.impl.RevalidationHandler;
+import org.apache.xerces.impl.dtd.XMLDTDLoader;
+import org.apache.xerces.parsers.DOMParserImpl;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.xni.grammars.XMLGrammarDescription;
+import org.apache.xml.serialize.DOMSerializerImpl;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSOutput;
+import org.w3c.dom.ls.LSParser;
+import org.w3c.dom.ls.LSSerializer;
+
+/**
+ * The DOMImplementation class is description of a particular
+ * implementation of the Document Object Model. As such its data is
+ * static, shared by all instances of this implementation.
+ *
+ * The DOM API requires that it be a real object rather than static
+ * methods. However, there's nothing that says it can't be a singleton,
+ * so that's how I've implemented it.
+ *
+ * This particular class, along with CoreDocumentImpl, supports the DOM
+ * Core and Load/Save (Experimental). Optional modules are supported by
+ * the more complete DOMImplementation class along with DocumentImpl.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class CoreDOMImplementationImpl
+ implements DOMImplementation, DOMImplementationLS {
+
+ //
+ // Data
+ //
+
+ // validator pools
+ private static final int SIZE = 2;
+
+ private SoftReference schemaValidators[] = new SoftReference[SIZE];
+ private SoftReference xml10DTDValidators[] = new SoftReference[SIZE];
+ private SoftReference xml11DTDValidators[] = new SoftReference[SIZE];
+
+ private int freeSchemaValidatorIndex = -1;
+ private int freeXML10DTDValidatorIndex = -1;
+ private int freeXML11DTDValidatorIndex = -1;
+
+ private int schemaValidatorsCurrentSize = SIZE;
+ private int xml10DTDValidatorsCurrentSize = SIZE;
+ private int xml11DTDValidatorsCurrentSize = SIZE;
+
+ private SoftReference xml10DTDLoaders[] = new SoftReference[SIZE];
+ private SoftReference xml11DTDLoaders[] = new SoftReference[SIZE];
+
+ private int freeXML10DTDLoaderIndex = -1;
+ private int freeXML11DTDLoaderIndex = -1;
+
+ private int xml10DTDLoaderCurrentSize = SIZE;
+ private int xml11DTDLoaderCurrentSize = SIZE;
+
+ // Document and doctype counter. Used to assign order to documents and
+ // doctypes without owners, on an demand basis. Used for
+ // compareDocumentPosition
+ private int docAndDoctypeCounter = 0;
+
+ // static
+ /** Dom implementation singleton. */
+ static final CoreDOMImplementationImpl singleton = new CoreDOMImplementationImpl();
+
+ //
+ // Public methods
+ //
+ /** NON-DOM: Obtain and return the single shared object */
+ public static DOMImplementation getDOMImplementation() {
+ return singleton;
+ }
+ //
+ // DOMImplementation methods
+ //
+ /**
+ * Test if the DOM implementation supports a specific "feature" --
+ * currently meaning language and level thereof.
+ *
+ * @param feature The package name of the feature to test.
+ * In Level 1, supported values are "HTML" and "XML" (case-insensitive).
+ * At this writing, org.apache.xerces.dom supports only XML.
+ *
+ * @param version The version number of the feature being tested.
+ * This is interpreted as "Version of the DOM API supported for the
+ * specified Feature", and in Level 1 should be "1.0"
+ *
+ * @return true iff this implementation is compatible with the specified
+ * feature and version.
+ */
+ public boolean hasFeature(String feature, String version) {
+
+ boolean anyVersion = version == null || version.length() == 0;
+
+ // check if Xalan implementation is around and if yes report true for supporting
+ // XPath API
+ // if a plus sign "+" is prepended to any feature name, implementations
+ // are considered in which the specified feature may not be directly
+ // castable DOMImplementation.getFeature(feature, version). Without a
+ // plus, only features whose interfaces are directly castable are considered.
+ if ((feature.equalsIgnoreCase("+XPath"))
+ && (anyVersion || version.equals("3.0"))) {
+ try {
+ Class xpathClass = ObjectFactory.findProviderClass(
+ "org.apache.xpath.domapi.XPathEvaluatorImpl",
+ ObjectFactory.findClassLoader(), true);
+
+ // Check if the DOM XPath implementation implements
+ // the interface org.w3c.dom.XPathEvaluator
+ Class interfaces[] = xpathClass.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ if (interfaces[i].getName().equals(
+ "org.w3c.dom.xpath.XPathEvaluator")) {
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ return false;
+ }
+ return true;
+ }
+ if (feature.startsWith("+")) {
+ feature = feature.substring(1);
+ }
+ return (
+ feature.equalsIgnoreCase("Core")
+ && (anyVersion
+ || version.equals("1.0")
+ || version.equals("2.0")
+ || version.equals("3.0")))
+ || (feature.equalsIgnoreCase("XML")
+ && (anyVersion
+ || version.equals("1.0")
+ || version.equals("2.0")
+ || version.equals("3.0")))
+ || (feature.equalsIgnoreCase("XMLVersion")
+ && (anyVersion
+ || version.equals("1.0")
+ || version.equals("1.1")))
+ || (feature.equalsIgnoreCase("LS")
+ && (anyVersion
+ || version.equals("3.0")))
+ || (feature.equalsIgnoreCase("ElementTraversal")
+ && (anyVersion
+ || version.equals("1.0")));
+ } // hasFeature(String,String):boolean
+
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Creates an empty DocumentType node.
+ *
+ * @param qualifiedName The qualified name of the document type to be created.
+ * @param publicID The document type public identifier.
+ * @param systemID The document type system identifier.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public DocumentType createDocumentType( String qualifiedName,
+ String publicID, String systemID) {
+ // REVISIT: this might allow creation of invalid name for DOCTYPE
+ // xmlns prefix.
+ // also there is no way for a user to turn off error checking.
+ checkQName(qualifiedName);
+ return new DocumentTypeImpl(null, qualifiedName, publicID, systemID);
+ }
+
+ final void checkQName(String qname){
+ int index = qname.indexOf(':');
+ int lastIndex = qname.lastIndexOf(':');
+ int length = qname.length();
+
+ // it is an error for NCName to have more than one ':'
+ // check if it is valid QName [Namespace in XML production 6]
+ if (index == 0 || index == length - 1 || lastIndex != index) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NAMESPACE_ERR",
+ null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ int start = 0;
+ // Namespace in XML production [6]
+ if (index > 0) {
+ // check that prefix is NCName
+ if (!XMLChar.isNCNameStart(qname.charAt(start))) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "INVALID_CHARACTER_ERR",
+ null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ for (int i = 1; i < index; i++) {
+ if (!XMLChar.isNCName(qname.charAt(i))) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "INVALID_CHARACTER_ERR",
+ null);
+ throw new DOMException(
+ DOMException.INVALID_CHARACTER_ERR,
+ msg);
+ }
+ }
+ start = index + 1;
+ }
+
+ // check local part
+ if (!XMLChar.isNCNameStart(qname.charAt(start))) {
+ // REVISIT: add qname parameter to the message
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "INVALID_CHARACTER_ERR",
+ null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ for (int i = start + 1; i < length; i++) {
+ if (!XMLChar.isNCName(qname.charAt(i))) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "INVALID_CHARACTER_ERR",
+ null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ }
+ }
+
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Creates an XML Document object of the specified type with its document
+ * element.
+ *
+ * @param namespaceURI The namespace URI of the document
+ * element to create, or null.
+ * @param qualifiedName The qualified name of the document
+ * element to create.
+ * @param doctype The type of document to be created or null.
+ *
+ * When doctype is not null, its
+ * Node.ownerDocument attribute is set to
+ * the document being created.
+ * @return Document A new Document object.
+ * @throws DOMException WRONG_DOCUMENT_ERR: Raised if doctype has
+ * already been used with a different document.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public Document createDocument(
+ String namespaceURI,
+ String qualifiedName,
+ DocumentType doctype)
+ throws DOMException {
+ if (doctype != null && doctype.getOwnerDocument() != null) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "WRONG_DOCUMENT_ERR",
+ null);
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+ }
+ CoreDocumentImpl doc = createDocument(doctype);
+ // If namespaceURI and qualifiedName are null return a Document with no document element.
+ if (qualifiedName != null || namespaceURI != null) {
+ Element e = doc.createElementNS(namespaceURI, qualifiedName);
+ doc.appendChild(e);
+ }
+ return doc;
+ }
+
+ protected CoreDocumentImpl createDocument(DocumentType doctype) {
+ return new CoreDocumentImpl(doctype);
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ */
+ public Object getFeature(String feature, String version) {
+ if (singleton.hasFeature(feature, version)) {
+ if ((feature.equalsIgnoreCase("+XPath"))) {
+ try {
+ Class xpathClass = ObjectFactory.findProviderClass(
+ "org.apache.xpath.domapi.XPathEvaluatorImpl",
+ ObjectFactory.findClassLoader(), true);
+
+ // Check if the DOM XPath implementation implements
+ // the interface org.w3c.dom.XPathEvaluator
+ Class interfaces[] = xpathClass.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ if (interfaces[i].getName().equals(
+ "org.w3c.dom.xpath.XPathEvaluator")) {
+ return xpathClass.newInstance();
+ }
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ } else {
+ return singleton;
+ }
+ }
+ return null;
+ }
+
+ // DOM L3 LS
+
+ /**
+ * DOM Level 3 LS CR - Experimental.
+ * Create a new LSParser . The newly constructed parser may
+ * then be configured by means of its DOMConfiguration
+ * object, and used to parse documents by means of its parse
+ * method.
+ * @param mode The mode argument is either
+ * MODE_SYNCHRONOUS or MODE_ASYNCHRONOUS , if
+ * mode is MODE_SYNCHRONOUS then the
+ * LSParser that is created will operate in synchronous
+ * mode, if it's MODE_ASYNCHRONOUS then the
+ * LSParser that is created will operate in asynchronous
+ * mode.
+ * @param schemaType An absolute URI representing the type of the schema
+ * language used during the load of a Document using the
+ * newly created LSParser . Note that no lexical checking
+ * is done on the absolute URI. In order to create a
+ * LSParser for any kind of schema types (i.e. the
+ * LSParser will be free to use any schema found), use the value
+ * null .
+ * Note: For W3C XML Schema [XML Schema Part 1]
+ * , applications must use the value
+ * "http://www.w3.org/2001/XMLSchema" . For XML DTD [XML 1.0],
+ * applications must use the value
+ * "http://www.w3.org/TR/REC-xml" . Other Schema languages
+ * are outside the scope of the W3C and therefore should recommend an
+ * absolute URI in order to use this method.
+ * @return The newly created LSParser object. This
+ * LSParser is either synchronous or asynchronous
+ * depending on the value of the mode argument.
+ * Note: By default, the newly created LSParser
+ * does not contain a DOMErrorHandler , i.e. the value of
+ * the "
+ * error-handler" configuration parameter is null . However, implementations
+ * may provide a default error handler at creation time. In that case,
+ * the initial value of the "error-handler" configuration
+ * parameter on the new created LSParser contains a
+ * reference to the default error handler.
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if the requested mode or schema type is
+ * not supported.
+ */
+ public LSParser createLSParser(short mode, String schemaType)
+ throws DOMException {
+ if (mode != DOMImplementationLS.MODE_SYNCHRONOUS || (schemaType !=null &&
+ !"http://www.w3.org/2001/XMLSchema".equals(schemaType) &&
+ !"http://www.w3.org/TR/REC-xml".equals(schemaType))) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NOT_SUPPORTED_ERR",
+ null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+ if (schemaType != null
+ && schemaType.equals("http://www.w3.org/TR/REC-xml")) {
+ return new DOMParserImpl(
+ "org.apache.xerces.parsers.XML11DTDConfiguration",
+ schemaType);
+ }
+ else {
+ // create default parser configuration validating against XMLSchemas
+ return new DOMParserImpl(
+ "org.apache.xerces.parsers.XIncludeAwareParserConfiguration",
+ schemaType);
+ }
+ }
+
+ /**
+ * DOM Level 3 LS CR - Experimental.
+ * Create a new LSSerializer object.
+ * @return The newly created LSSerializer object.
+ * Note: By default, the newly created
+ * LSSerializer has no DOMErrorHandler ,
+ * i.e. the value of the "error-handler" configuration
+ * parameter is null . However, implementations may
+ * provide a default error handler at creation time. In that case, the
+ * initial value of the "error-handler" configuration
+ * parameter on the new created LSSerializer contains a
+ * reference to the default error handler.
+ */
+ public LSSerializer createLSSerializer() {
+ try {
+ Class serializerClass = ObjectFactory.findProviderClass(
+ "org.apache.xml.serializer.dom3.LSSerializerImpl",
+ ObjectFactory.findClassLoader(), true);
+ return (LSSerializer) serializerClass.newInstance();
+ }
+ catch (Exception e) {}
+ // Fall back to Xerces' deprecated serializer if
+ // the Xalan based serializer is unavailable.
+ return new DOMSerializerImpl();
+ }
+
+ /**
+ * DOM Level 3 LS CR - Experimental.
+ * Create a new empty input source.
+ * @return The newly created input object.
+ */
+ public LSInput createLSInput() {
+ return new DOMInputImpl();
+ }
+
+ //
+ // Protected methods
+ //
+ /** NON-DOM: retrieve validator. */
+ synchronized RevalidationHandler getValidator(String schemaType, String xmlVersion) {
+ if (schemaType == XMLGrammarDescription.XML_SCHEMA) {
+ // create new validator - we should not attempt
+ // to restrict the number of validation handlers being
+ // requested
+ while (freeSchemaValidatorIndex >= 0) {
+ // return first available validator
+ SoftReference ref = schemaValidators[freeSchemaValidatorIndex];
+ RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
+ if (holder != null && holder.handler != null) {
+ RevalidationHandler val = holder.handler;
+ holder.handler = null;
+ --freeSchemaValidatorIndex;
+ return val;
+ }
+ schemaValidators[freeSchemaValidatorIndex--] = null;
+ }
+ return (RevalidationHandler) (ObjectFactory
+ .newInstance(
+ "org.apache.xerces.impl.xs.XMLSchemaValidator",
+ ObjectFactory.findClassLoader(),
+ true));
+ }
+ else if(schemaType == XMLGrammarDescription.XML_DTD) {
+ // return an instance of XML11DTDValidator
+ if ("1.1".equals(xmlVersion)) {
+ while (freeXML11DTDValidatorIndex >= 0) {
+ // return first available validator
+ SoftReference ref = xml11DTDValidators[freeXML11DTDValidatorIndex];
+ RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
+ if (holder != null && holder.handler != null) {
+ RevalidationHandler val = holder.handler;
+ holder.handler = null;
+ --freeXML11DTDValidatorIndex;
+ return val;
+ }
+ xml11DTDValidators[freeXML11DTDValidatorIndex--] = null;
+ }
+ return (RevalidationHandler) (ObjectFactory
+ .newInstance(
+ "org.apache.xerces.impl.dtd.XML11DTDValidator",
+ ObjectFactory.findClassLoader(),
+ true));
+ }
+ // return an instance of XMLDTDValidator
+ else {
+ while (freeXML10DTDValidatorIndex >= 0) {
+ // return first available validator
+ SoftReference ref = xml10DTDValidators[freeXML10DTDValidatorIndex];
+ RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
+ if (holder != null && holder.handler != null) {
+ RevalidationHandler val = holder.handler;
+ holder.handler = null;
+ --freeXML10DTDValidatorIndex;
+ return val;
+ }
+ xml10DTDValidators[freeXML10DTDValidatorIndex--] = null;
+ }
+ return (RevalidationHandler) (ObjectFactory
+ .newInstance(
+ "org.apache.xerces.impl.dtd.XMLDTDValidator",
+ ObjectFactory.findClassLoader(),
+ true));
+ }
+ }
+ return null;
+ }
+
+ /** NON-DOM: release validator */
+ synchronized void releaseValidator(String schemaType, String xmlVersion,
+ RevalidationHandler validator) {
+ if (schemaType == XMLGrammarDescription.XML_SCHEMA) {
+ ++freeSchemaValidatorIndex;
+ if (schemaValidators.length == freeSchemaValidatorIndex) {
+ // resize size of the validators
+ schemaValidatorsCurrentSize += SIZE;
+ SoftReference newarray[] = new SoftReference[schemaValidatorsCurrentSize];
+ System.arraycopy(schemaValidators, 0, newarray, 0, schemaValidators.length);
+ schemaValidators = newarray;
+ }
+ SoftReference ref = schemaValidators[freeSchemaValidatorIndex];
+ if (ref != null) {
+ RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
+ if (holder != null) {
+ holder.handler = validator;
+ return;
+ }
+ }
+ schemaValidators[freeSchemaValidatorIndex] = new SoftReference(new RevalidationHandlerHolder(validator));
+ }
+ else if (schemaType == XMLGrammarDescription.XML_DTD) {
+ // release an instance of XML11DTDValidator
+ if ("1.1".equals(xmlVersion)) {
+ ++freeXML11DTDValidatorIndex;
+ if (xml11DTDValidators.length == freeXML11DTDValidatorIndex) {
+ // resize size of the validators
+ xml11DTDValidatorsCurrentSize += SIZE;
+ SoftReference [] newarray = new SoftReference[xml11DTDValidatorsCurrentSize];
+ System.arraycopy(xml11DTDValidators, 0, newarray, 0, xml11DTDValidators.length);
+ xml11DTDValidators = newarray;
+ }
+ SoftReference ref = xml11DTDValidators[freeXML11DTDValidatorIndex];
+ if (ref != null) {
+ RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
+ if (holder != null) {
+ holder.handler = validator;
+ return;
+ }
+ }
+ xml11DTDValidators[freeXML11DTDValidatorIndex] = new SoftReference(new RevalidationHandlerHolder(validator));
+ }
+ // release an instance of XMLDTDValidator
+ else {
+ ++freeXML10DTDValidatorIndex;
+ if (xml10DTDValidators.length == freeXML10DTDValidatorIndex) {
+ // resize size of the validators
+ xml10DTDValidatorsCurrentSize += SIZE;
+ SoftReference [] newarray = new SoftReference[xml10DTDValidatorsCurrentSize];
+ System.arraycopy(xml10DTDValidators, 0, newarray, 0, xml10DTDValidators.length);
+ xml10DTDValidators = newarray;
+ }
+ SoftReference ref = xml10DTDValidators[freeXML10DTDValidatorIndex];
+ if (ref != null) {
+ RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
+ if (holder != null) {
+ holder.handler = validator;
+ return;
+ }
+ }
+ xml10DTDValidators[freeXML10DTDValidatorIndex] = new SoftReference(new RevalidationHandlerHolder(validator));
+ }
+ }
+ }
+
+ /** NON-DOM: retrieve DTD loader */
+ synchronized final XMLDTDLoader getDTDLoader(String xmlVersion) {
+ // return an instance of XML11DTDProcessor
+ if ("1.1".equals(xmlVersion)) {
+ while (freeXML11DTDLoaderIndex >= 0) {
+ // return first available DTD loader
+ SoftReference ref = xml11DTDLoaders[freeXML11DTDLoaderIndex];
+ XMLDTDLoaderHolder holder = (XMLDTDLoaderHolder) ref.get();
+ if (holder != null && holder.loader != null) {
+ XMLDTDLoader val = holder.loader;
+ holder.loader = null;
+ --freeXML11DTDLoaderIndex;
+ return val;
+ }
+ xml11DTDLoaders[freeXML11DTDLoaderIndex--] = null;
+ }
+ return (XMLDTDLoader) (ObjectFactory
+ .newInstance(
+ "org.apache.xerces.impl.dtd.XML11DTDProcessor",
+ ObjectFactory.findClassLoader(),
+ true));
+ }
+ // return an instance of XMLDTDLoader
+ else {
+ while (freeXML10DTDLoaderIndex >= 0) {
+ // return first available DTD loader
+ SoftReference ref = xml10DTDLoaders[freeXML10DTDLoaderIndex];
+ XMLDTDLoaderHolder holder = (XMLDTDLoaderHolder) ref.get();
+ if (holder != null && holder.loader != null) {
+ XMLDTDLoader val = holder.loader;
+ holder.loader = null;
+ --freeXML10DTDLoaderIndex;
+ return val;
+ }
+ xml10DTDLoaders[freeXML10DTDLoaderIndex--] = null;
+ }
+ return new XMLDTDLoader();
+ }
+ }
+
+ /** NON-DOM: release DTD loader */
+ synchronized final void releaseDTDLoader(String xmlVersion, XMLDTDLoader loader) {
+ // release an instance of XMLDTDLoader
+ if ("1.1".equals(xmlVersion)) {
+ ++freeXML11DTDLoaderIndex;
+ if (xml11DTDLoaders.length == freeXML11DTDLoaderIndex) {
+ // resize size of the DTD loaders
+ xml11DTDLoaderCurrentSize += SIZE;
+ SoftReference [] newarray = new SoftReference[xml11DTDLoaderCurrentSize];
+ System.arraycopy(xml11DTDLoaders, 0, newarray, 0, xml11DTDLoaders.length);
+ xml11DTDLoaders = newarray;
+ }
+ SoftReference ref = xml11DTDLoaders[freeXML11DTDLoaderIndex];
+ if (ref != null) {
+ XMLDTDLoaderHolder holder = (XMLDTDLoaderHolder) ref.get();
+ if (holder != null) {
+ holder.loader = loader;
+ return;
+ }
+ }
+ xml11DTDLoaders[freeXML11DTDLoaderIndex] = new SoftReference(new XMLDTDLoaderHolder(loader));
+ }
+ // release an instance of XMLDTDLoader
+ else {
+ ++freeXML10DTDLoaderIndex;
+ if (xml10DTDLoaders.length == freeXML10DTDLoaderIndex) {
+ // resize size of the DTD loaders
+ xml10DTDLoaderCurrentSize += SIZE;
+ SoftReference [] newarray = new SoftReference[xml10DTDLoaderCurrentSize];
+ System.arraycopy(xml10DTDLoaders, 0, newarray, 0, xml10DTDLoaders.length);
+ xml10DTDLoaders = newarray;
+ }
+ SoftReference ref = xml10DTDLoaders[freeXML10DTDLoaderIndex];
+ if (ref != null) {
+ XMLDTDLoaderHolder holder = (XMLDTDLoaderHolder) ref.get();
+ if (holder != null) {
+ holder.loader = loader;
+ return;
+ }
+ }
+ xml10DTDLoaders[freeXML10DTDLoaderIndex] = new SoftReference(new XMLDTDLoaderHolder(loader));
+ }
+ }
+
+ /** NON-DOM: increment document/doctype counter */
+ protected synchronized int assignDocumentNumber() {
+ return ++docAndDoctypeCounter;
+ }
+
+ /** NON-DOM: increment document/doctype counter */
+ protected synchronized int assignDocTypeNumber() {
+ return ++docAndDoctypeCounter;
+ }
+
+ /**
+ * DOM Level 3 LS CR - Experimental.
+ *
+ * Create a new empty output destination object where
+ * LSOutput.characterStream ,
+ * LSOutput.byteStream , LSOutput.systemId ,
+ * LSOutput.encoding are null.
+ * @return The newly created output object.
+ */
+ public LSOutput createLSOutput() {
+ return new DOMOutputImpl();
+ }
+
+ /**
+ * A holder for RevalidationHandlers. This allows us to reuse
+ * SoftReferences which haven't yet been cleared by the garbage
+ * collector.
+ */
+ static final class RevalidationHandlerHolder {
+ RevalidationHandlerHolder(RevalidationHandler handler) {
+ this.handler = handler;
+ }
+ RevalidationHandler handler;
+ }
+
+ /**
+ * A holder for XMLDTDLoaders. This allows us to reuse SoftReferences
+ * which haven't yet been cleared by the garbage collector.
+ */
+ static final class XMLDTDLoaderHolder {
+ XMLDTDLoaderHolder(XMLDTDLoader loader) {
+ this.loader = loader;
+ }
+ XMLDTDLoader loader;
+ }
+
+} // class DOMImplementationImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/CoreDocumentImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/CoreDocumentImpl.java
new file mode 100644
index 0000000..0646520
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/CoreDocumentImpl.java
@@ -0,0 +1,2815 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.reflect.Constructor;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.apache.xerces.util.URI;
+import org.apache.xerces.util.XML11Char;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.xni.NamespaceContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DOMConfiguration;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Entity;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Notation;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+import org.w3c.dom.UserDataHandler;
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSSerializer;
+
+/**
+ * The Document interface represents the entire HTML or XML document.
+ * Conceptually, it is the root of the document tree, and provides the
+ * primary access to the document's data.
+ *
+ * Since elements, text nodes, comments, processing instructions,
+ * etc. cannot exist outside the context of a Document, the Document
+ * interface also contains the factory methods needed to create these
+ * objects. The Node objects created have a ownerDocument attribute
+ * which associates them with the Document within whose context they
+ * were created.
+ *
+ * The CoreDocumentImpl class only implements the DOM Core. Additional modules
+ * are supported by the more complete DocumentImpl subclass.
+ *
+ * Note: When any node in the document is serialized, the
+ * entire document is serialized along with it.
+ *
+ * @xerces.internal
+ *
+ * @author Arnaud Le Hors, IBM
+ * @author Joe Kesselman, IBM
+ * @author Andy Clark, IBM
+ * @author Ralf Pfeiffer, IBM
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+
+
+public class CoreDocumentImpl
+extends ParentNode implements Document {
+
+ /**TODO::
+ * 1. Change XML11Char method names similar to XMLChar. That will prevent lot
+ * of dirty version checking code.
+ *
+ * 2. IMO during cloneNode qname/isXMLName check should not be made.
+ */
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 0;
+
+ //
+ // Data
+ //
+
+ // document information
+
+ /** Document type. */
+ protected DocumentTypeImpl docType;
+
+ /** Document element. */
+ protected ElementImpl docElement;
+
+ /** NodeListCache free list */
+ transient NodeListCache fFreeNLCache;
+
+ /**Experimental DOM Level 3 feature: Document encoding */
+ protected String encoding;
+
+ /**Experimental DOM Level 3 feature: Document actualEncoding */
+ protected String actualEncoding;
+
+ /**Experimental DOM Level 3 feature: Document version */
+ protected String version;
+
+ /**Experimental DOM Level 3 feature: Document standalone */
+ protected boolean standalone;
+
+ /**Experimental DOM Level 3 feature: documentURI */
+ protected String fDocumentURI;
+
+ /** Table for user data attached to this document nodes. */
+ protected Map userData; // serialized as Hashtable
+
+ /** Identifiers. */
+ protected Hashtable identifiers;
+
+ // DOM Level 3: normalizeDocument
+ transient DOMNormalizer domNormalizer = null;
+ transient DOMConfigurationImpl fConfiguration = null;
+
+ // support of XPath API
+ transient Object fXPathEvaluator = null;
+
+ /** Table for quick check of child insertion. */
+ private final static int[] kidOK;
+
+ /**
+ * Number of alterations made to this document since its creation.
+ * Serves as a "dirty bit" so that live objects such as NodeList can
+ * recognize when an alteration has been made and discard its cached
+ * state information.
+ *
+ * Any method that alters the tree structure MUST cause or be
+ * accompanied by a call to changed(), to inform it that any outstanding
+ * NodeLists may have to be updated.
+ *
+ * (Required because NodeList is simultaneously "live" and integer-
+ * indexed -- a bad decision in the DOM's design.)
+ *
+ * Note that changes which do not affect the tree's structure -- changing
+ * the node's name, for example -- do _not_ have to call changed().
+ *
+ * Alternative implementation would be to use a cryptographic
+ * Digest value rather than a count. This would have the advantage that
+ * "harmless" changes (those producing equal() trees) would not force
+ * NodeList to resynchronize. Disadvantage is that it's slightly more prone
+ * to "false negatives", though that's the difference between "wildly
+ * unlikely" and "absurdly unlikely". IF we start maintaining digests,
+ * we should consider taking advantage of them.
+ *
+ * Note: This used to be done a node basis, so that we knew what
+ * subtree changed. But since only DeepNodeList really use this today,
+ * the gain appears to be really small compared to the cost of having
+ * an int on every (parent) node plus having to walk up the tree all the
+ * way to the root to mark the branch as changed everytime a node is
+ * changed.
+ * So we now have a single counter global to the document. It means that
+ * some objects may flush their cache more often than necessary, but this
+ * makes nodes smaller and only the document needs to be marked as changed.
+ */
+ protected int changes = 0;
+
+ // experimental
+
+ /** Allow grammar access. */
+ protected boolean allowGrammarAccess;
+
+ /** Bypass error checking. */
+ protected boolean errorChecking = true;
+
+ //Did version change at any point when the document was created ?
+ //this field helps us to optimize when normalizingDocument.
+ protected boolean xmlVersionChanged = false ;
+
+ /** The following are required for compareDocumentPosition
+ */
+ // Document number. Documents are ordered across the implementation using
+ // positive integer values. Documents are assigned numbers on demand.
+ private int documentNumber=0;
+ // Node counter and table. Used to assign numbers to nodes for this
+ // document. Node number values are negative integers. Nodes are
+ // assigned numbers on demand.
+ private int nodeCounter = 0;
+ private Map nodeTable; // serialized as Hashtable
+ private boolean xml11Version = false; //by default 1.0
+ //
+ // Static initialization
+ //
+
+ static {
+
+ kidOK = new int[13];
+
+ kidOK[DOCUMENT_NODE] =
+ 1 << ELEMENT_NODE | 1 << PROCESSING_INSTRUCTION_NODE |
+ 1 << COMMENT_NODE | 1 << DOCUMENT_TYPE_NODE;
+
+ kidOK[DOCUMENT_FRAGMENT_NODE] =
+ kidOK[ENTITY_NODE] =
+ kidOK[ENTITY_REFERENCE_NODE] =
+ kidOK[ELEMENT_NODE] =
+ 1 << ELEMENT_NODE | 1 << PROCESSING_INSTRUCTION_NODE |
+ 1 << COMMENT_NODE | 1 << TEXT_NODE |
+ 1 << CDATA_SECTION_NODE | 1 << ENTITY_REFERENCE_NODE ;
+
+
+ kidOK[ATTRIBUTE_NODE] =
+ 1 << TEXT_NODE | 1 << ENTITY_REFERENCE_NODE;
+
+ kidOK[DOCUMENT_TYPE_NODE] =
+ kidOK[PROCESSING_INSTRUCTION_NODE] =
+ kidOK[COMMENT_NODE] =
+ kidOK[TEXT_NODE] =
+ kidOK[CDATA_SECTION_NODE] =
+ kidOK[NOTATION_NODE] =
+ 0;
+
+ } // static
+
+ //
+ // Constructors
+ //
+
+ /**
+ * NON-DOM: Actually creating a Document is outside the DOM's spec,
+ * since it has to operate in terms of a particular implementation.
+ */
+ public CoreDocumentImpl() {
+ this(false);
+ }
+
+ /** Constructor. */
+ public CoreDocumentImpl(boolean grammarAccess) {
+ super(null);
+ ownerDocument = this;
+ allowGrammarAccess = grammarAccess;
+ }
+
+ /**
+ * For DOM2 support.
+ * The createDocument factory method is in DOMImplementation.
+ */
+ public CoreDocumentImpl(DocumentType doctype) {
+ this(doctype, false);
+ }
+
+ /** For DOM2 support. */
+ public CoreDocumentImpl(DocumentType doctype, boolean grammarAccess) {
+ this(grammarAccess);
+ if (doctype != null) {
+ DocumentTypeImpl doctypeImpl;
+ try {
+ doctypeImpl = (DocumentTypeImpl) doctype;
+ } catch (ClassCastException e) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+ }
+ doctypeImpl.ownerDocument = this;
+ appendChild(doctype);
+ }
+ }
+
+ //
+ // Node methods
+ //
+
+ // even though ownerDocument refers to this in this implementation
+ // the DOM Level 2 spec says it must be null, so make it appear so
+ final public Document getOwnerDocument() {
+ return null;
+ }
+
+ /** Returns the node type. */
+ public short getNodeType() {
+ return Node.DOCUMENT_NODE;
+ }
+
+ /** Returns the node name. */
+ public String getNodeName() {
+ return "#document";
+ }
+
+ /**
+ * Deep-clone a document, including fixing ownerDoc for the cloned
+ * children. Note that this requires bypassing the WRONG_DOCUMENT_ERR
+ * protection. I've chosen to implement it by calling importNode
+ * which is DOM Level 2.
+ *
+ * @return org.w3c.dom.Node
+ * @param deep boolean, iff true replicate children
+ */
+ public Node cloneNode(boolean deep) {
+
+ CoreDocumentImpl newdoc = new CoreDocumentImpl();
+ callUserDataHandlers(this, newdoc, UserDataHandler.NODE_CLONED);
+ cloneNode(newdoc, deep);
+
+ return newdoc;
+
+ } // cloneNode(boolean):Node
+
+
+ /**
+ * internal method to share code with subclass
+ **/
+ protected void cloneNode(CoreDocumentImpl newdoc, boolean deep) {
+
+ // clone the children by importing them
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+
+ if (deep) {
+ HashMap reversedIdentifiers = null;
+ if (identifiers != null) {
+ // Build a reverse mapping from element to identifier.
+ reversedIdentifiers = new HashMap();
+ Iterator entries = identifiers.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ Object elementId = entry.getKey();
+ Object elementNode = entry.getValue();
+ reversedIdentifiers.put(elementNode, elementId);
+ }
+ }
+
+ // Copy children into new document.
+ for (ChildNode kid = firstChild; kid != null;
+ kid = kid.nextSibling) {
+ newdoc.appendChild(newdoc.importNode(kid, true, true,
+ reversedIdentifiers));
+ }
+ }
+
+ // experimental
+ newdoc.allowGrammarAccess = allowGrammarAccess;
+ newdoc.errorChecking = errorChecking;
+
+ } // cloneNode(CoreDocumentImpl,boolean):void
+
+ /**
+ * Since a Document may contain at most one top-level Element child,
+ * and at most one DocumentType declaraction, we need to subclass our
+ * add-children methods to implement this constraint.
+ * Since appendChild() is implemented as insertBefore(,null),
+ * altering the latter fixes both.
+ *
+ * While I'm doing so, I've taken advantage of the opportunity to
+ * cache documentElement and docType so we don't have to
+ * search for them.
+ *
+ * REVISIT: According to the spec it is not allowed to alter neither the
+ * document element nor the document type in any way
+ */
+ public Node insertBefore(Node newChild, Node refChild)
+ throws DOMException {
+
+ // Only one such child permitted
+ int type = newChild.getNodeType();
+ if (errorChecking) {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ if((type == Node.ELEMENT_NODE && docElement != null) ||
+ (type == Node.DOCUMENT_TYPE_NODE && docType != null)) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null);
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, msg);
+ }
+ }
+ // Adopt orphan doctypes
+ if (newChild.getOwnerDocument() == null &&
+ newChild instanceof DocumentTypeImpl) {
+ ((DocumentTypeImpl) newChild).ownerDocument = this;
+ }
+ super.insertBefore(newChild,refChild);
+
+ // If insert succeeded, cache the kid appropriately
+ if (type == Node.ELEMENT_NODE) {
+ docElement = (ElementImpl)newChild;
+ }
+ else if (type == Node.DOCUMENT_TYPE_NODE) {
+ docType = (DocumentTypeImpl)newChild;
+ }
+
+ return newChild;
+
+ } // insertBefore(Node,Node):Node
+
+ /**
+ * Since insertBefore caches the docElement (and, currently, docType),
+ * removeChild has to know how to undo the cache
+ *
+ * REVISIT: According to the spec it is not allowed to alter neither the
+ * document element nor the document type in any way
+ */
+ public Node removeChild(Node oldChild) throws DOMException {
+
+ super.removeChild(oldChild);
+
+ // If remove succeeded, un-cache the kid appropriately
+ int type = oldChild.getNodeType();
+ if(type == Node.ELEMENT_NODE) {
+ docElement = null;
+ }
+ else if (type == Node.DOCUMENT_TYPE_NODE) {
+ docType = null;
+ }
+
+ return oldChild;
+
+ } // removeChild(Node):Node
+
+ /**
+ * Since we cache the docElement (and, currently, docType),
+ * replaceChild has to update the cache
+ *
+ * REVISIT: According to the spec it is not allowed to alter neither the
+ * document element nor the document type in any way
+ */
+ public Node replaceChild(Node newChild, Node oldChild)
+ throws DOMException {
+
+ // Adopt orphan doctypes
+ if (newChild.getOwnerDocument() == null &&
+ newChild instanceof DocumentTypeImpl) {
+ ((DocumentTypeImpl) newChild).ownerDocument = this;
+ }
+
+ if (errorChecking &&((docType != null &&
+ oldChild.getNodeType() != Node.DOCUMENT_TYPE_NODE &&
+ newChild.getNodeType() == Node.DOCUMENT_TYPE_NODE)
+ || (docElement != null &&
+ oldChild.getNodeType() != Node.ELEMENT_NODE &&
+ newChild.getNodeType() == Node.ELEMENT_NODE))) {
+
+ throw new DOMException(
+ DOMException.HIERARCHY_REQUEST_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null));
+ }
+ super.replaceChild(newChild, oldChild);
+
+ int type = oldChild.getNodeType();
+ if(type == Node.ELEMENT_NODE) {
+ docElement = (ElementImpl)newChild;
+ }
+ else if (type == Node.DOCUMENT_TYPE_NODE) {
+ docType = (DocumentTypeImpl)newChild;
+ }
+ return oldChild;
+ } // replaceChild(Node,Node):Node
+
+ /*
+ * Get Node text content
+ * @since DOM Level 3
+ */
+ public String getTextContent() throws DOMException {
+ return null;
+ }
+
+ /*
+ * Set Node text content
+ * @since DOM Level 3
+ */
+ public void setTextContent(String textContent)
+ throws DOMException {
+ // no-op
+ }
+
+ /**
+ * @since DOM Level 3
+ */
+ public Object getFeature(String feature, String version) {
+
+ boolean anyVersion = version == null || version.length() == 0;
+
+ // if a plus sign "+" is prepended to any feature name, implementations
+ // are considered in which the specified feature may not be directly
+ // castable DOMImplementation.getFeature(feature, version). Without a
+ // plus, only features whose interfaces are directly castable are
+ // considered.
+ if ((feature.equalsIgnoreCase("+XPath"))
+ && (anyVersion || version.equals("3.0"))) {
+
+ // If an XPathEvaluator was created previously
+ // return it otherwise create a new one.
+ if (fXPathEvaluator != null) {
+ return fXPathEvaluator;
+ }
+
+ try {
+ Class xpathClass = ObjectFactory.findProviderClass(
+ "org.apache.xpath.domapi.XPathEvaluatorImpl",
+ ObjectFactory.findClassLoader(), true);
+ Constructor xpathClassConstr =
+ xpathClass.getConstructor(new Class[] { Document.class });
+
+ // Check if the DOM XPath implementation implements
+ // the interface org.w3c.dom.XPathEvaluator
+ Class interfaces[] = xpathClass.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ if (interfaces[i].getName().equals(
+ "org.w3c.dom.xpath.XPathEvaluator")) {
+ fXPathEvaluator = xpathClassConstr.newInstance(new Object[] { this });
+ return fXPathEvaluator;
+ }
+ }
+ return null;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ return super.getFeature(feature, version);
+ }
+
+ //
+ // Document methods
+ //
+
+ // factory methods
+
+ /**
+ * Factory method; creates an Attribute having this Document as its
+ * OwnerDoc.
+ *
+ * @param name The name of the attribute. Note that the attribute's value is
+ * _not_ established at the factory; remember to set it!
+ *
+ * @throws DOMException(INVALID_NAME_ERR)
+ * if the attribute name is not acceptable.
+ */
+ public Attr createAttribute(String name)
+ throws DOMException {
+
+ if (errorChecking && !isXMLName(name,xml11Version)) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "INVALID_CHARACTER_ERR",
+ null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ return new AttrImpl(this, name);
+
+ } // createAttribute(String):Attr
+
+ /**
+ * Factory method; creates a CDATASection having this Document as
+ * its OwnerDoc.
+ *
+ * @param data The initial contents of the CDATA
+ *
+ * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents. (HTML
+ * not yet implemented.)
+ */
+ public CDATASection createCDATASection(String data)
+ throws DOMException {
+ return new CDATASectionImpl(this, data);
+ }
+
+ /**
+ * Factory method; creates a Comment having this Document as its
+ * OwnerDoc.
+ *
+ * @param data The initial contents of the Comment. */
+ public Comment createComment(String data) {
+ return new CommentImpl(this, data);
+ }
+
+ /**
+ * Factory method; creates a DocumentFragment having this Document
+ * as its OwnerDoc.
+ */
+ public DocumentFragment createDocumentFragment() {
+ return new DocumentFragmentImpl(this);
+ }
+
+ /**
+ * Factory method; creates an Element having this Document
+ * as its OwnerDoc.
+ *
+ * @param tagName The name of the element type to instantiate. For
+ * XML, this is case-sensitive. For HTML, the tagName parameter may
+ * be provided in any case, but it must be mapped to the canonical
+ * uppercase form by the DOM implementation.
+ *
+ * @throws DOMException(INVALID_NAME_ERR) if the tag name is not
+ * acceptable.
+ */
+ public Element createElement(String tagName)
+ throws DOMException {
+
+ if (errorChecking && !isXMLName(tagName,xml11Version)) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ return new ElementImpl(this, tagName);
+
+ } // createElement(String):Element
+
+ /**
+ * Factory method; creates an EntityReference having this Document
+ * as its OwnerDoc.
+ *
+ * @param name The name of the Entity we wish to refer to
+ *
+ * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents, where
+ * nonstandard entities are not permitted. (HTML not yet
+ * implemented.)
+ */
+ public EntityReference createEntityReference(String name)
+ throws DOMException {
+
+ if (errorChecking && !isXMLName(name,xml11Version)) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ return new EntityReferenceImpl(this, name);
+
+ } // createEntityReference(String):EntityReference
+
+ /**
+ * Factory method; creates a ProcessingInstruction having this Document
+ * as its OwnerDoc.
+ *
+ * @param target The target "processor channel"
+ * @param data Parameter string to be passed to the target.
+ *
+ * @throws DOMException(INVALID_NAME_ERR) if the target name is not
+ * acceptable.
+ *
+ * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents. (HTML
+ * not yet implemented.)
+ */
+ public ProcessingInstruction createProcessingInstruction(String target,
+ String data)
+ throws DOMException {
+
+ if (errorChecking && !isXMLName(target,xml11Version)) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ return new ProcessingInstructionImpl(this, target, data);
+
+ } // createProcessingInstruction(String,String):ProcessingInstruction
+
+ /**
+ * Factory method; creates a Text node having this Document as its
+ * OwnerDoc.
+ *
+ * @param data The initial contents of the Text.
+ */
+ public Text createTextNode(String data) {
+ return new TextImpl(this, data);
+ }
+
+ // other document methods
+
+ /**
+ * For XML, this provides access to the Document Type Definition.
+ * For HTML documents, and XML documents which don't specify a DTD,
+ * it will be null.
+ */
+ public DocumentType getDoctype() {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return docType;
+ }
+
+
+ /**
+ * Convenience method, allowing direct access to the child node
+ * which is considered the root of the actual document content. For
+ * HTML, where it is legal to have more than one Element at the top
+ * level of the document, we pick the one with the tagName
+ * "HTML". For XML there should be only one top-level
+ *
+ * (HTML not yet supported.)
+ */
+ public Element getDocumentElement() {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return docElement;
+ }
+
+ /**
+ * Return a live collection of all descendent Elements (not just
+ * immediate children) having the specified tag name.
+ *
+ * @param tagname The type of Element we want to gather. "*" will be
+ * taken as a wildcard, meaning "all elements in the document."
+ *
+ * @see DeepNodeListImpl
+ */
+ public NodeList getElementsByTagName(String tagname) {
+ return new DeepNodeListImpl(this,tagname);
+ }
+
+ /**
+ * Retrieve information describing the abilities of this particular
+ * DOM implementation. Intended to support applications that may be
+ * using DOMs retrieved from several different sources, potentially
+ * with different underlying representations.
+ */
+ public DOMImplementation getImplementation() {
+ // Currently implemented as a singleton, since it's hardcoded
+ // information anyway.
+ return CoreDOMImplementationImpl.getDOMImplementation();
+ }
+
+ //
+ // Public methods
+ //
+
+ // properties
+
+ /**
+ * Sets whether the DOM implementation performs error checking
+ * upon operations. Turning off error checking only affects
+ * the following DOM checks:
+ *
+ * - Checking strings to make sure that all characters are
+ * legal XML characters
+ *
- Hierarchy checking such as allowed children, checks for
+ * cycles, etc.
+ *
+ *
+ * Turning off error checking does not turn off the
+ * following checks:
+ *
+ * - Read only checks
+ *
- Checks related to DOM events
+ *
+ */
+
+ public void setErrorChecking(boolean check) {
+ errorChecking = check;
+ }
+
+ /*
+ * DOM Level 3 WD - Experimental.
+ */
+ public void setStrictErrorChecking(boolean check) {
+ errorChecking = check;
+ }
+
+ /**
+ * Returns true if the DOM implementation performs error checking.
+ */
+ public boolean getErrorChecking() {
+ return errorChecking;
+ }
+
+ /*
+ * DOM Level 3 WD - Experimental.
+ */
+ public boolean getStrictErrorChecking() {
+ return errorChecking;
+ }
+
+
+ /**
+ * DOM Level 3 CR - Experimental. (Was getActualEncoding)
+ *
+ * An attribute specifying the encoding used for this document
+ * at the time of the parsing. This is null when
+ * it is not known, such as when the Document was
+ * created in memory.
+ * @since DOM Level 3
+ */
+ public String getInputEncoding() {
+ return actualEncoding;
+ }
+
+ /**
+ * DOM Internal
+ * (Was a DOM L3 Core WD public interface method setActualEncoding )
+ *
+ * An attribute specifying the actual encoding of this document. This is
+ * null otherwise.
+ * This attribute represents the property [character encoding scheme]
+ * defined in .
+ */
+ public void setInputEncoding(String value) {
+ actualEncoding = value;
+ }
+
+ /**
+ * DOM Internal
+ * (Was a DOM L3 Core WD public interface method setXMLEncoding )
+ *
+ * An attribute specifying, as part of the XML declaration,
+ * the encoding of this document. This is null when unspecified.
+ */
+ public void setXmlEncoding(String value) {
+ encoding = value;
+ }
+
+ /**
+ * @deprecated This method is internal and only exists for
+ * compatibility with older applications. New applications
+ * should never call this method.
+ */
+ public void setEncoding(String value) {
+ setXmlEncoding(value);
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * The encoding of this document (part of XML Declaration)
+ */
+ public String getXmlEncoding() {
+ return encoding;
+ }
+
+ /**
+ * @deprecated This method is internal and only exists for
+ * compatibility with older applications. New applications
+ * should never call this method.
+ */
+ public String getEncoding() {
+ return getXmlEncoding();
+ }
+
+ /**
+ * DOM Level 3 CR - Experimental.
+ * version - An attribute specifying, as part of the XML declaration,
+ * the version number of this document.
+ */
+ public void setXmlVersion(String value) {
+ if(value.equals("1.0") || value.equals("1.1")){
+ //we need to change the flag value only --
+ // when the version set is different than already set.
+ if(!getXmlVersion().equals(value)){
+ xmlVersionChanged = true ;
+ //change the normalization value back to false
+ isNormalized(false);
+ version = value;
+ }
+ }
+ else{
+ //NOT_SUPPORTED_ERR: Raised if the vesion is set to a value that is not supported by
+ //this document
+ //we dont support any other XML version
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+
+ }
+ if((getXmlVersion()).equals("1.1")){
+ xml11Version = true;
+ }
+ else{
+ xml11Version = false;
+ }
+ }
+
+ /**
+ * @deprecated This method is internal and only exists for
+ * compatibility with older applications. New applications
+ * should never call this method.
+ */
+ public void setVersion(String value) {
+ setXmlVersion(value);
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * The version of this document (part of XML Declaration)
+ */
+ public String getXmlVersion() {
+ return (version == null)?"1.0":version;
+ }
+
+ /**
+ * @deprecated This method is internal and only exists for
+ * compatibility with older applications. New applications
+ * should never call this method.
+ */
+ public String getVersion() {
+ return getXmlVersion();
+ }
+
+ /**
+ * DOM Level 3 CR - Experimental.
+ *
+ * Xmlstandalone - An attribute specifying, as part of the XML declaration,
+ * whether this document is standalone
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if this document does not support the
+ * "XML" feature.
+ * @since DOM Level 3
+ */
+ public void setXmlStandalone(boolean value)
+ throws DOMException {
+ standalone = value;
+ }
+
+ /**
+ * @deprecated This method is internal and only exists for
+ * compatibility with older applications. New applications
+ * should never call this method.
+ */
+ public void setStandalone(boolean value) {
+ setXmlStandalone(value);
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * standalone that specifies whether this document is standalone
+ * (part of XML Declaration)
+ */
+ public boolean getXmlStandalone() {
+ return standalone;
+ }
+
+ /**
+ * @deprecated This method is internal and only exists for
+ * compatibility with older applications. New applications
+ * should never call this method.
+ */
+ public boolean getStandalone() {
+ return getXmlStandalone();
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * The location of the document or null if undefined.
+ * Beware that when the Document supports the feature
+ * "HTML" , the href attribute of the HTML BASE element takes precedence
+ * over this attribute.
+ * @since DOM Level 3
+ */
+ public String getDocumentURI(){
+ return fDocumentURI;
+ }
+
+
+ /* NON-DOM
+ * Used by DOM Level 3 WD remameNode.
+ *
+ * Some DOM implementations do not allow nodes to be renamed and require
+ * creating new elements.
+ * In this case this method should be overwritten.
+ *
+ * @return true if the given element can be renamed, false, if it must be replaced.
+ */
+ protected boolean canRenameElements(String newNamespaceURI, String newNodeName, ElementImpl el) {
+ return true;
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * Renaming node
+ */
+ public Node renameNode(Node n,String namespaceURI,String name)
+ throws DOMException{
+
+ if (errorChecking && n.getOwnerDocument() != this && n != this) {
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+ }
+ switch (n.getNodeType()) {
+ case ELEMENT_NODE: {
+ ElementImpl el = (ElementImpl) n;
+ if (el instanceof ElementNSImpl) {
+ if (canRenameElements(namespaceURI, name, el)) {
+ ((ElementNSImpl) el).rename(namespaceURI, name);
+ // fire user data NODE_RENAMED event
+ callUserDataHandlers(el, null, UserDataHandler.NODE_RENAMED);
+ }
+ else {
+ el = replaceRenameElement(el, namespaceURI, name);
+ }
+ }
+ else {
+ if (namespaceURI == null && canRenameElements(null, name, el)) {
+ el.rename(name);
+ // fire user data NODE_RENAMED event
+ callUserDataHandlers(el, null, UserDataHandler.NODE_RENAMED);
+ }
+ else {
+ el = replaceRenameElement(el, namespaceURI, name);
+ }
+ }
+ // fire ElementNameChanged event
+ renamedElement((Element) n, el);
+ return el;
+ }
+ case ATTRIBUTE_NODE: {
+ AttrImpl at = (AttrImpl) n;
+
+ // detach attr from element
+ Element el = at.getOwnerElement();
+ if (el != null) {
+ el.removeAttributeNode(at);
+ }
+ if (n instanceof AttrNSImpl) {
+ ((AttrNSImpl) at).rename(namespaceURI, name);
+ // reattach attr to element
+ if (el != null) {
+ el.setAttributeNodeNS(at);
+ }
+
+ // fire user data NODE_RENAMED event
+ callUserDataHandlers(at, null, UserDataHandler.NODE_RENAMED);
+ }
+ else {
+ if (namespaceURI == null) {
+ at.rename(name);
+ // reattach attr to element
+ if (el != null) {
+ el.setAttributeNode(at);
+ }
+
+ // fire user data NODE_RENAMED event
+ callUserDataHandlers(at, null, UserDataHandler.NODE_RENAMED);
+ }
+ else {
+ // we need to create a new object
+ AttrNSImpl nat = (AttrNSImpl) createAttributeNS(namespaceURI, name);
+
+ // register event listeners on new node
+ copyEventListeners(at, nat);
+
+ // remove user data from old node
+ Hashtable data = removeUserDataTable(at);
+
+ // move children to new node
+ Node child = at.getFirstChild();
+ while (child != null) {
+ at.removeChild(child);
+ nat.appendChild(child);
+ child = at.getFirstChild();
+ }
+
+ // attach user data to new node
+ setUserDataTable(nat, data);
+
+ // and fire user data NODE_RENAMED event
+ callUserDataHandlers(at, nat, UserDataHandler.NODE_RENAMED);
+
+ // reattach attr to element
+ if (el != null) {
+ el.setAttributeNode(nat);
+ }
+ at = nat;
+ }
+ }
+ // fire AttributeNameChanged event
+ renamedAttrNode((Attr) n, at);
+
+ return at;
+ }
+ default: {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+ }
+
+ }
+
+ private ElementImpl replaceRenameElement(ElementImpl el, String namespaceURI, String name) {
+
+ // we need to create a new object
+ ElementNSImpl nel = (ElementNSImpl)createElementNS(namespaceURI, name);
+
+ // register event listeners on new node
+ copyEventListeners(el, nel);
+
+ // remove user data from old node
+ Hashtable data = removeUserDataTable(el);
+
+ // remove old node from parent if any
+ Node parent = el.getParentNode();
+ Node nextSib = el.getNextSibling();
+ if (parent != null) {
+ parent.removeChild(el);
+ }
+ // move children to new node
+ Node child = el.getFirstChild();
+ while (child != null) {
+ el.removeChild(child);
+ nel.appendChild(child);
+ child = el.getFirstChild();
+ }
+ // move specified attributes to new node
+ nel.moveSpecifiedAttributes(el);
+
+ // attach user data to new node
+ setUserDataTable(nel, data);
+
+ // and fire user data NODE_RENAMED event
+ callUserDataHandlers(el, nel,
+ UserDataHandler.NODE_RENAMED);
+
+ // insert new node where old one was
+ if (parent != null) {
+ parent.insertBefore(nel, nextSib);
+ }
+ return nel;
+ }
+
+
+ /**
+ * DOM Level 3 WD - Experimental
+ * Normalize document.
+ */
+ public void normalizeDocument(){
+ // No need to normalize if already normalized.
+ if (isNormalized() && !isNormalizeDocRequired()) {
+ return;
+ }
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+
+ if (domNormalizer == null) {
+ domNormalizer = new DOMNormalizer();
+ }
+
+ if (fConfiguration == null) {
+ fConfiguration = new DOMConfigurationImpl();
+ }
+ else {
+ fConfiguration.reset();
+ }
+
+ domNormalizer.normalizeDocument(this, fConfiguration);
+ isNormalized(true);
+ //set the XMLversion changed value to false -- once we have finished
+ //doing normalization
+ xmlVersionChanged = false ;
+ }
+
+
+ /**
+ * DOM Level 3 CR - Experimental
+ *
+ * The configuration used when Document.normalizeDocument is
+ * invoked.
+ * @since DOM Level 3
+ */
+ public DOMConfiguration getDomConfig(){
+ if (fConfiguration == null) {
+ fConfiguration = new DOMConfigurationImpl();
+ }
+ return fConfiguration;
+ }
+
+
+ /**
+ * Returns the absolute base URI of this node or null if the implementation
+ * wasn't able to obtain an absolute URI. Note: If the URI is malformed, a
+ * null is returned.
+ *
+ * @return The absolute base URI of this node or null.
+ * @since DOM Level 3
+ */
+ public String getBaseURI() {
+ if (fDocumentURI != null && fDocumentURI.length() != 0 ) {// attribute value is always empty string
+ try {
+ return new URI(fDocumentURI).toString();
+ }
+ catch (org.apache.xerces.util.URI.MalformedURIException e){
+ // REVISIT: what should happen in this case?
+ return null;
+ }
+ }
+ return fDocumentURI;
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ */
+ public void setDocumentURI(String documentURI){
+ fDocumentURI = documentURI;
+ }
+
+
+ //
+ // DOM L3 LS
+ //
+ /**
+ * DOM Level 3 WD - Experimental.
+ * Indicates whether the method load should be synchronous or
+ * asynchronous. When the async attribute is set to true
+ * the load method returns control to the caller before the document has
+ * completed loading. The default value of this property is
+ * false .
+ * Setting the value of this attribute might throw NOT_SUPPORTED_ERR
+ * if the implementation doesn't support the mode the attribute is being
+ * set to. Should the DOM spec define the default value of this
+ * property? What if implementing both async and sync IO is impractical
+ * in some systems? 2001-09-14. default is false but we
+ * need to check with Mozilla and IE.
+ */
+ public boolean getAsync() {
+ return false;
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * Indicates whether the method load should be synchronous or
+ * asynchronous. When the async attribute is set to true
+ * the load method returns control to the caller before the document has
+ * completed loading. The default value of this property is
+ * false .
+ * Setting the value of this attribute might throw NOT_SUPPORTED_ERR
+ * if the implementation doesn't support the mode the attribute is being
+ * set to. Should the DOM spec define the default value of this
+ * property? What if implementing both async and sync IO is impractical
+ * in some systems? 2001-09-14. default is false but we
+ * need to check with Mozilla and IE.
+ */
+ public void setAsync(boolean async) {
+ if (async) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+ }
+ /**
+ * DOM Level 3 WD - Experimental.
+ * If the document is currently being loaded as a result of the method
+ * load being invoked the loading and parsing is
+ * immediately aborted. The possibly partial result of parsing the
+ * document is discarded and the document is cleared.
+ */
+ public void abort() {
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ *
+ * Replaces the content of the document with the result of parsing the
+ * given URI. Invoking this method will either block the caller or
+ * return to the caller immediately depending on the value of the async
+ * attribute. Once the document is fully loaded a "load" event (as
+ * defined in [DOM Level 3 Events]
+ * , except that the Event.targetNode will be the document,
+ * not an element) will be dispatched on the document. If an error
+ * occurs, an implementation dependent "error" event will be dispatched
+ * on the document. If this method is called on a document that is
+ * currently loading, the current load is interrupted and the new URI
+ * load is initiated.
+ * When invoking this method the parameters used in the
+ * DOMParser interface are assumed to have their default
+ * values with the exception that the parameters "entities"
+ * , "normalize-characters" ,
+ * "check-character-normalization" are set to
+ * "false" .
+ * The result of a call to this method is the same the result of a
+ * call to DOMParser.parseWithContext with an input stream
+ * referencing the URI that was passed to this call, the document as the
+ * context node, and the action ACTION_REPLACE_CHILDREN .
+ * @param uri The URI reference for the XML file to be loaded. If this is
+ * a relative URI, the base URI used by the implementation is
+ * implementation dependent.
+ * @return If async is set to true load returns
+ * true if the document load was successfully initiated.
+ * If an error occurred when initiating the document load,
+ * load returns false .If async is set to
+ * false load returns true if
+ * the document was successfully loaded and parsed. If an error
+ * occurred when either loading or parsing the URI, load
+ * returns false .
+ */
+ public boolean load(String uri) {
+ return false;
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * Replace the content of the document with the result of parsing the
+ * input string, this method is always synchronous.
+ * @param source A string containing an XML document.
+ * @return true if parsing the input string succeeded
+ * without errors, otherwise false .
+ */
+ public boolean loadXML(String source) {
+ return false;
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * Save the document or the given node and all its descendants to a string
+ * (i.e. serialize the document or node).
+ * The parameters used in the LSSerializer interface are
+ * assumed to have their default values when invoking this method.
+ * The result of a call to this method is the same the result of a
+ * call to LSSerializer.writeToString with the document as
+ * the node to write.
+ * @param node Specifies what to serialize, if this parameter is
+ * null the whole document is serialized, if it's
+ * non-null the given node is serialized.
+ * @return The serialized document or null in case an error
+ * occurred.
+ * @exception DOMException
+ * WRONG_DOCUMENT_ERR: Raised if the node passed in as the node
+ * parameter is from an other document.
+ */
+ public String saveXML(Node node)
+ throws DOMException {
+ if ( errorChecking && node != null &&
+ this != node.getOwnerDocument() ) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+ }
+ DOMImplementationLS domImplLS = (DOMImplementationLS)DOMImplementationImpl.getDOMImplementation();
+ LSSerializer xmlWriter = domImplLS.createLSSerializer();
+ if (node == null) {
+ node = this;
+ }
+ return xmlWriter.writeToString(node);
+ }
+
+ /**
+ * Sets whether the DOM implementation generates mutation events
+ * upon operations.
+ */
+ void setMutationEvents(boolean set) {
+ // does nothing by default - overidden in subclass
+ }
+
+ /**
+ * Returns true if the DOM implementation generates mutation events.
+ */
+ boolean getMutationEvents() {
+ // does nothing by default - overriden in subclass
+ return false;
+ }
+
+
+
+ // non-DOM factory methods
+
+ /**
+ * NON-DOM
+ * Factory method; creates a DocumentType having this Document
+ * as its OwnerDoc. (REC-DOM-Level-1-19981001 left the process of building
+ * DTD information unspecified.)
+ *
+ * @param qualifiedName
+ * @param publicID
+ * @param systemID
+ *
+ * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents, where
+ * DTDs are not permitted. (HTML not yet implemented.)
+ */
+ public DocumentType createDocumentType(String qualifiedName,
+ String publicID,
+ String systemID)
+ throws DOMException {
+
+ return new DocumentTypeImpl(this, qualifiedName, publicID, systemID);
+
+ } // createDocumentType(String):DocumentType
+
+ /**
+ * NON-DOM
+ * Factory method; creates an Entity having this Document
+ * as its OwnerDoc. (REC-DOM-Level-1-19981001 left the process of building
+ * DTD information unspecified.)
+ *
+ * @param name The name of the Entity we wish to provide a value for.
+ *
+ * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents, where
+ * nonstandard entities are not permitted. (HTML not yet
+ * implemented.)
+ */
+ public Entity createEntity(String name)
+ throws DOMException {
+
+
+ if (errorChecking && !isXMLName(name,xml11Version)) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ return new EntityImpl(this, name);
+
+ } // createEntity(String):Entity
+
+ /**
+ * NON-DOM
+ * Factory method; creates a Notation having this Document
+ * as its OwnerDoc. (REC-DOM-Level-1-19981001 left the process of building
+ * DTD information unspecified.)
+ *
+ * @param name The name of the Notation we wish to describe
+ *
+ * @throws DOMException(NOT_SUPPORTED_ERR) for HTML documents, where
+ * notations are not permitted. (HTML not yet
+ * implemented.)
+ */
+ public Notation createNotation(String name)
+ throws DOMException {
+
+ if (errorChecking && !isXMLName(name,xml11Version)) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ return new NotationImpl(this, name);
+
+ } // createNotation(String):Notation
+
+ /**
+ * NON-DOM Factory method: creates an element definition. Element
+ * definitions hold default attribute values.
+ */
+ public ElementDefinitionImpl createElementDefinition(String name)
+ throws DOMException {
+
+ if (errorChecking && !isXMLName(name,xml11Version)) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ return new ElementDefinitionImpl(this, name);
+
+ } // createElementDefinition(String):ElementDefinitionImpl
+
+ // other non-DOM methods
+
+ /** NON-DOM: Get the number associated with this document. Used to
+ * order documents in the implementation.
+ */
+ protected int getNodeNumber() {
+ if (documentNumber==0) {
+
+ CoreDOMImplementationImpl cd = (CoreDOMImplementationImpl)CoreDOMImplementationImpl.getDOMImplementation();
+ documentNumber = cd.assignDocumentNumber();
+ }
+ return documentNumber;
+ }
+
+
+ /** NON-DOM: Get a number associated with a node created with respect
+ * to this document. Needed for compareDocumentPosition when nodes
+ * are disconnected. This is only used on demand.
+ */
+ protected int getNodeNumber(Node node) {
+
+ // Check if the node is already in the hash
+ // If so, retrieve the node number
+ // If not, assign a number to the node
+ // Node numbers are negative, from -1 to -n
+ int num;
+ if (nodeTable == null) {
+ nodeTable = new WeakHashMap();
+ num = --nodeCounter;
+ nodeTable.put(node, new Integer(num));
+ }
+ else {
+ Integer n = (Integer)nodeTable.get(node);
+ if (n== null) {
+ num = --nodeCounter;
+ nodeTable.put(node, new Integer(num));
+ }
+ else
+ num = n.intValue();
+ }
+ return num;
+ }
+
+ /**
+ * Copies a node from another document to this document. The new nodes are
+ * created using this document's factory methods and are populated with the
+ * data from the source's accessor methods defined by the DOM interfaces.
+ * Its behavior is otherwise similar to that of cloneNode.
+ *
+ * According to the DOM specifications, document nodes cannot be imported
+ * and a NOT_SUPPORTED_ERR exception is thrown if attempted.
+ */
+ public Node importNode(Node source, boolean deep)
+ throws DOMException {
+ return importNode(source, deep, false, null);
+ } // importNode(Node,boolean):Node
+
+ /**
+ * Overloaded implementation of DOM's importNode method. This method
+ * provides the core functionality for the public importNode and cloneNode
+ * methods.
+ *
+ * The reversedIdentifiers parameter is provided for cloneNode to
+ * preserve the document's identifiers. The HashMap has Elements as the
+ * keys and their identifiers as the values. When an element is being
+ * imported, a check is done for an associated identifier. If one exists,
+ * the identifier is registered with the new, imported element. If
+ * reversedIdentifiers is null, the parameter is not applied.
+ */
+ private Node importNode(Node source, boolean deep, boolean cloningDoc,
+ HashMap reversedIdentifiers)
+ throws DOMException {
+ Node newnode=null;
+ Hashtable userData = null;
+
+ // Sigh. This doesn't work; too many nodes have private data that
+ // would have to be manually tweaked. May be able to add local
+ // shortcuts to each nodetype. Consider ?????
+ // if(source instanceof NodeImpl &&
+ // !(source instanceof DocumentImpl))
+ // {
+ // // Can't clone DocumentImpl since it invokes us...
+ // newnode=(NodeImpl)source.cloneNode(false);
+ // newnode.ownerDocument=this;
+ // }
+ // else
+ if(source instanceof NodeImpl)
+ userData = ((NodeImpl)source).getUserDataRecord();
+ int type = source.getNodeType();
+ switch (type) {
+ case ELEMENT_NODE: {
+ Element newElement;
+ boolean domLevel20 = source.getOwnerDocument().getImplementation().hasFeature("XML", "2.0");
+ // Create element according to namespace support/qualification.
+ if(domLevel20 == false || source.getLocalName() == null)
+ newElement = createElement(source.getNodeName());
+ else
+ newElement = createElementNS(source.getNamespaceURI(),
+ source.getNodeName());
+
+ // Copy element's attributes, if any.
+ NamedNodeMap sourceAttrs = source.getAttributes();
+ if (sourceAttrs != null) {
+ int length = sourceAttrs.getLength();
+ for (int index = 0; index < length; index++) {
+ Attr attr = (Attr)sourceAttrs.item(index);
+
+ // NOTE: this methods is used for both importingNode
+ // and cloning the document node. In case of the
+ // clonning default attributes should be copied.
+ // But for importNode defaults should be ignored.
+ if (attr.getSpecified() || cloningDoc) {
+ Attr newAttr = (Attr)importNode(attr, true, cloningDoc,
+ reversedIdentifiers);
+
+ // Attach attribute according to namespace
+ // support/qualification.
+ if (domLevel20 == false ||
+ attr.getLocalName() == null)
+ newElement.setAttributeNode(newAttr);
+ else
+ newElement.setAttributeNodeNS(newAttr);
+ }
+ }
+ }
+
+ // Register element identifier.
+ if (reversedIdentifiers != null) {
+ // Does element have an associated identifier?
+ Object elementId = reversedIdentifiers.get(source);
+ if (elementId != null) {
+ if (identifiers == null)
+ identifiers = new Hashtable();
+
+ identifiers.put(elementId, newElement);
+ }
+ }
+
+ newnode = newElement;
+ break;
+ }
+
+ case ATTRIBUTE_NODE: {
+
+ if( source.getOwnerDocument().getImplementation().hasFeature("XML", "2.0") ){
+ if (source.getLocalName() == null) {
+ newnode = createAttribute(source.getNodeName());
+ } else {
+ newnode = createAttributeNS(source.getNamespaceURI(),
+ source.getNodeName());
+ }
+ }
+ else {
+ newnode = createAttribute(source.getNodeName());
+ }
+ // if source is an AttrImpl from this very same implementation
+ // avoid creating the child nodes if possible
+ if (source instanceof AttrImpl) {
+ AttrImpl attr = (AttrImpl) source;
+ if (attr.hasStringValue()) {
+ AttrImpl newattr = (AttrImpl) newnode;
+ newattr.setValue(attr.getValue());
+ deep = false;
+ }
+ else {
+ deep = true;
+ }
+ }
+ else {
+ // According to the DOM spec the kids carry the value.
+ // However, there are non compliant implementations out
+ // there that fail to do so. To avoid ending up with no
+ // value at all, in this case we simply copy the text value
+ // directly.
+ if (source.getFirstChild() == null) {
+ newnode.setNodeValue(source.getNodeValue());
+ deep = false;
+ } else {
+ deep = true;
+ }
+ }
+ break;
+ }
+
+ case TEXT_NODE: {
+ newnode = createTextNode(source.getNodeValue());
+ break;
+ }
+
+ case CDATA_SECTION_NODE: {
+ newnode = createCDATASection(source.getNodeValue());
+ break;
+ }
+
+ case ENTITY_REFERENCE_NODE: {
+ newnode = createEntityReference(source.getNodeName());
+ // the subtree is created according to this doc by the method
+ // above, so avoid carrying over original subtree
+ deep = false;
+ break;
+ }
+
+ case ENTITY_NODE: {
+ Entity srcentity = (Entity)source;
+ EntityImpl newentity =
+ (EntityImpl)createEntity(source.getNodeName());
+ newentity.setPublicId(srcentity.getPublicId());
+ newentity.setSystemId(srcentity.getSystemId());
+ newentity.setNotationName(srcentity.getNotationName());
+ // Kids carry additional value,
+ // allow deep import temporarily
+ newentity.isReadOnly(false);
+ newnode = newentity;
+ break;
+ }
+
+ case PROCESSING_INSTRUCTION_NODE: {
+ newnode = createProcessingInstruction(source.getNodeName(),
+ source.getNodeValue());
+ break;
+ }
+
+ case COMMENT_NODE: {
+ newnode = createComment(source.getNodeValue());
+ break;
+ }
+
+ case DOCUMENT_TYPE_NODE: {
+ // unless this is used as part of cloning a Document
+ // forbid it for the sake of being compliant to the DOM spec
+ if (!cloningDoc) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+ DocumentType srcdoctype = (DocumentType)source;
+ DocumentTypeImpl newdoctype = (DocumentTypeImpl)
+ createDocumentType(srcdoctype.getNodeName(),
+ srcdoctype.getPublicId(),
+ srcdoctype.getSystemId());
+ newdoctype.setInternalSubset(srcdoctype.getInternalSubset());
+ // Values are on NamedNodeMaps
+ NamedNodeMap smap = srcdoctype.getEntities();
+ NamedNodeMap tmap = newdoctype.getEntities();
+ if(smap != null) {
+ for(int i = 0; i < smap.getLength(); i++) {
+ tmap.setNamedItem(importNode(smap.item(i), true, true,
+ reversedIdentifiers));
+ }
+ }
+ smap = srcdoctype.getNotations();
+ tmap = newdoctype.getNotations();
+ if (smap != null) {
+ for(int i = 0; i < smap.getLength(); i++) {
+ tmap.setNamedItem(importNode(smap.item(i), true, true,
+ reversedIdentifiers));
+ }
+ }
+
+ // NOTE: At this time, the DOM definition of DocumentType
+ // doesn't cover Elements and their Attributes. domimpl's
+ // extentions in that area will not be preserved, even if
+ // copying from domimpl to domimpl. We could special-case
+ // that here. Arguably we should. Consider. ?????
+ newnode = newdoctype;
+ break;
+ }
+
+ case DOCUMENT_FRAGMENT_NODE: {
+ newnode = createDocumentFragment();
+ // No name, kids carry value
+ break;
+ }
+
+ case NOTATION_NODE: {
+ Notation srcnotation = (Notation)source;
+ NotationImpl newnotation =
+ (NotationImpl)createNotation(source.getNodeName());
+ newnotation.setPublicId(srcnotation.getPublicId());
+ newnotation.setSystemId(srcnotation.getSystemId());
+ // Kids carry additional value
+ newnode = newnotation;
+ // No name, no value
+ break;
+ }
+ case DOCUMENT_NODE : // Can't import document nodes
+ default: { // Unknown node type
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+ }
+
+ if(userData != null)
+ callUserDataHandlers(source, newnode, UserDataHandler.NODE_IMPORTED,userData);
+
+ // If deep, replicate and attach the kids.
+ if (deep) {
+ for (Node srckid = source.getFirstChild();
+ srckid != null;
+ srckid = srckid.getNextSibling()) {
+ newnode.appendChild(importNode(srckid, true, cloningDoc,
+ reversedIdentifiers));
+ }
+ }
+ if (newnode.getNodeType() == Node.ENTITY_NODE) {
+ ((NodeImpl)newnode).setReadOnly(true, true);
+ }
+ return newnode;
+
+ } // importNode(Node,boolean,boolean,Hashtable):Node
+
+ /**
+ * DOM Level 3 WD - Experimental
+ * Change the node's ownerDocument, and its subtree, to this Document
+ *
+ * @param source The node to adopt.
+ * @see #importNode
+ **/
+ public Node adoptNode(Node source) {
+ NodeImpl node;
+ Hashtable userData = null;
+ try {
+ node = (NodeImpl) source;
+ } catch (ClassCastException e) {
+ // source node comes from a different DOMImplementation
+ return null;
+ }
+
+ // Return null if the source is null
+
+ if (source == null) {
+ return null;
+ }
+ else if (source != null && source.getOwnerDocument() != null) {
+
+ DOMImplementation thisImpl = this.getImplementation();
+ DOMImplementation otherImpl = source.getOwnerDocument().getImplementation();
+
+ // when the source node comes from a different implementation.
+ if (thisImpl != otherImpl) {
+ // Adopting from a deferred DOM to a non-deferred DOM
+ if (thisImpl instanceof org.apache.xerces.dom.DOMImplementationImpl &&
+ otherImpl instanceof org.apache.xerces.dom.DeferredDOMImplementationImpl) {
+ // traverse the DOM and expand deferred nodes and then allow adoption
+ undeferChildren (node);
+ }
+ else if ( thisImpl instanceof org.apache.xerces.dom.DeferredDOMImplementationImpl
+ && otherImpl instanceof org.apache.xerces.dom.DOMImplementationImpl) {
+ // Adopting from a non-deferred DOM into a deferred DOM, this should be okay
+ }
+ else {
+ // Adopting between two dissimilar DOMs is not allowed
+ return null;
+ }
+ }
+ // Adopting from a deferred DOM into another deferred DOM
+ else if (otherImpl instanceof org.apache.xerces.dom.DeferredDOMImplementationImpl) {
+ // traverse the DOM and expand deferred nodes and then allow adoption
+ undeferChildren (node);
+ }
+ }
+
+ switch (node.getNodeType()) {
+ case ATTRIBUTE_NODE: {
+ AttrImpl attr = (AttrImpl) node;
+ // remove node from wherever it is
+ if( attr.getOwnerElement() != null){
+ //1. owner element attribute is set to null
+ attr.getOwnerElement().removeAttributeNode(attr);
+ }
+ //2. specified flag is set to true
+ attr.isSpecified(true);
+ userData = node.getUserDataRecord();
+
+ //3. change ownership
+ attr.setOwnerDocument(this);
+ if(userData != null )
+ setUserDataTable(node,userData);
+ break;
+ }
+ //entity, notation nodes are read only nodes.. so they can't be adopted.
+ //runtime will fall through to NOTATION_NODE
+ case ENTITY_NODE:
+ case NOTATION_NODE:{
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+
+ }
+ //document, documentype nodes can't be adopted.
+ //runtime will fall through to DocumentTypeNode
+ case DOCUMENT_NODE:
+ case DOCUMENT_TYPE_NODE: {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+ case ENTITY_REFERENCE_NODE: {
+ userData = node.getUserDataRecord();
+ // remove node from wherever it is
+ Node parent = node.getParentNode();
+ if (parent != null) {
+ parent.removeChild(source);
+ }
+ // discard its replacement value
+ Node child;
+ while ((child = node.getFirstChild()) != null) {
+ node.removeChild(child);
+ }
+ // change ownership
+ node.setOwnerDocument(this);
+ if(userData != null)
+ setUserDataTable(node,userData);
+ // set its new replacement value if any
+ if (docType == null) {
+ break;
+ }
+ NamedNodeMap entities = docType.getEntities();
+ Node entityNode = entities.getNamedItem(node.getNodeName());
+ if (entityNode == null) {
+ break;
+ }
+ for (child = entityNode.getFirstChild();
+ child != null; child = child.getNextSibling()) {
+ Node childClone = child.cloneNode(true);
+ node.appendChild(childClone);
+ }
+ break;
+ }
+ case ELEMENT_NODE: {
+ userData = node.getUserDataRecord();
+ // remove node from wherever it is
+ Node parent = node.getParentNode();
+ if (parent != null) {
+ parent.removeChild(source);
+ }
+ // change ownership
+ node.setOwnerDocument(this);
+ if(userData != null)
+ setUserDataTable(node,userData);
+ // reconcile default attributes
+ ((ElementImpl)node).reconcileDefaultAttributes();
+ break;
+ }
+ default: {
+ userData = node.getUserDataRecord();
+ // remove node from wherever it is
+ Node parent = node.getParentNode();
+ if (parent != null) {
+ parent.removeChild(source);
+ }
+ // change ownership
+ node.setOwnerDocument(this);
+ if(userData != null)
+ setUserDataTable(node,userData);
+ }
+ }
+
+ //DOM L3 Core CR
+ //http://www.w3.org/TR/2003/CR-DOM-Level-3-Core-20031107/core.html#UserDataHandler-ADOPTED
+ if(userData != null)
+ callUserDataHandlers(source, null, UserDataHandler.NODE_ADOPTED,userData);
+
+ return node;
+ }
+
+ /**
+ * Traverses the DOM Tree and expands deferred nodes and their
+ * children.
+ *
+ */
+ protected void undeferChildren(Node node) {
+
+ Node top = node;
+
+ while (null != node) {
+
+ if (((NodeImpl)node).needsSyncData()) {
+ ((NodeImpl)node).synchronizeData();
+ }
+
+ NamedNodeMap attributes = node.getAttributes();
+ if (attributes != null) {
+ int length = attributes.getLength();
+ for (int i = 0; i < length; ++i) {
+ undeferChildren(attributes.item(i));
+ }
+ }
+
+ Node nextNode = null;
+ nextNode = node.getFirstChild();
+
+ while (null == nextNode) {
+
+ if (top.equals(node))
+ break;
+
+ nextNode = node.getNextSibling();
+
+ if (null == nextNode) {
+ node = node.getParentNode();
+
+ if ((null == node) || (top.equals(node))) {
+ nextNode = null;
+ break;
+ }
+ }
+ }
+
+ node = nextNode;
+ }
+ }
+
+ // identifier maintenence
+ /**
+ * Introduced in DOM Level 2
+ * Returns the Element whose ID is given by elementId. If no such element
+ * exists, returns null. Behavior is not defined if more than one element
+ * has this ID.
+ *
+ * Note: The DOM implementation must have information that says which
+ * attributes are of type ID. Attributes with the name "ID" are not of type
+ * ID unless so defined. Implementations that do not know whether
+ * attributes are of type ID or not are expected to return null.
+ * @see #getIdentifier
+ */
+ public Element getElementById(String elementId) {
+ return getIdentifier(elementId);
+ }
+
+ /**
+ * Remove all identifiers from the ID table
+ */
+ protected final void clearIdentifiers(){
+ if (identifiers != null){
+ identifiers.clear();
+ }
+ }
+
+ /**
+ * Registers an identifier name with a specified element node.
+ * If the identifier is already registered, the new element
+ * node replaces the previous node. If the specified element
+ * node is null, removeIdentifier() is called.
+ *
+ * @see #getIdentifier
+ * @see #removeIdentifier
+ */
+ public void putIdentifier(String idName, Element element) {
+
+ if (element == null) {
+ removeIdentifier(idName);
+ return;
+ }
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ if (identifiers == null) {
+ identifiers = new Hashtable();
+ }
+
+ identifiers.put(idName, element);
+
+ } // putIdentifier(String,Element)
+
+ /**
+ * Returns a previously registered element with the specified
+ * identifier name, or null if no element is registered.
+ *
+ * @see #putIdentifier
+ * @see #removeIdentifier
+ */
+ public Element getIdentifier(String idName) {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ if (identifiers == null) {
+ return null;
+ }
+ Element elem = (Element) identifiers.get(idName);
+ if (elem != null) {
+ // check that the element is in the tree
+ Node parent = elem.getParentNode();
+ while (parent != null) {
+ if (parent == this) {
+ return elem;
+ }
+ parent = parent.getParentNode();
+ }
+ }
+ return null;
+ } // getIdentifier(String):Element
+
+ /**
+ * Removes a previously registered element with the specified
+ * identifier name.
+ *
+ * @see #putIdentifier
+ * @see #getIdentifier
+ */
+ public void removeIdentifier(String idName) {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ if (identifiers == null) {
+ return;
+ }
+
+ identifiers.remove(idName);
+
+ } // removeIdentifier(String)
+
+ /** Returns an enumeration registered of identifier names. */
+ public Enumeration getIdentifiers() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ if (identifiers == null) {
+ identifiers = new Hashtable();
+ }
+
+ return identifiers.keys();
+
+ } // getIdentifiers():Enumeration
+
+ //
+ // DOM2: Namespace methods
+ //
+
+ /**
+ * Introduced in DOM Level 2.
+ * Creates an element of the given qualified name and namespace URI.
+ * If the given namespaceURI is null or an empty string and the
+ * qualifiedName has a prefix that is "xml", the created element
+ * is bound to the predefined namespace
+ * "http://www.w3.org/XML/1998/namespace" [Namespaces].
+ * @param namespaceURI The namespace URI of the element to
+ * create.
+ * @param qualifiedName The qualified name of the element type to
+ * instantiate.
+ * @return Element A new Element object with the following attributes:
+ * @throws DOMException INVALID_CHARACTER_ERR: Raised if the specified
+ * name contains an invalid character.
+ * @throws DOMException NAMESPACE_ERR: Raised if the qualifiedName has a
+ * prefix that is "xml" and the namespaceURI is
+ * neither null nor an empty string nor
+ * "http://www.w3.org/XML/1998/namespace", or
+ * if the qualifiedName has a prefix different
+ * from "xml" and the namespaceURI is null or an
+ * empty string.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public Element createElementNS(String namespaceURI, String qualifiedName)
+ throws DOMException {
+ return new ElementNSImpl(this, namespaceURI, qualifiedName);
+ }
+
+ /**
+ * NON-DOM: a factory method used by the Xerces DOM parser
+ * to create an element.
+ *
+ * @param namespaceURI The namespace URI of the element to
+ * create.
+ * @param qualifiedName The qualified name of the element type to
+ * instantiate.
+ * @param localpart The local name of the attribute to instantiate.
+ *
+ * @return Element A new Element object with the following attributes:
+ * @exception DOMException INVALID_CHARACTER_ERR: Raised if the specified
+ * name contains an invalid character.
+ */
+ public Element createElementNS(String namespaceURI, String qualifiedName,
+ String localpart)
+ throws DOMException {
+ return new ElementNSImpl(this, namespaceURI, qualifiedName, localpart);
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ * Creates an attribute of the given qualified name and namespace URI.
+ * If the given namespaceURI is null or an empty string and the
+ * qualifiedName has a prefix that is "xml", the created element
+ * is bound to the predefined namespace
+ * "http://www.w3.org/XML/1998/namespace" [Namespaces].
+ *
+ * @param namespaceURI The namespace URI of the attribute to
+ * create. When it is null or an empty string,
+ * this method behaves like createAttribute.
+ * @param qualifiedName The qualified name of the attribute to
+ * instantiate.
+ * @return Attr A new Attr object.
+ * @throws DOMException INVALID_CHARACTER_ERR: Raised if the specified
+ * name contains an invalid character.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public Attr createAttributeNS(String namespaceURI, String qualifiedName)
+ throws DOMException {
+ return new AttrNSImpl(this, namespaceURI, qualifiedName);
+ }
+
+ /**
+ * NON-DOM: a factory method used by the Xerces DOM parser
+ * to create an element.
+ *
+ * @param namespaceURI The namespace URI of the attribute to
+ * create. When it is null or an empty string,
+ * this method behaves like createAttribute.
+ * @param qualifiedName The qualified name of the attribute to
+ * instantiate.
+ * @param localpart The local name of the attribute to instantiate.
+ *
+ * @return Attr A new Attr object.
+ * @throws DOMException INVALID_CHARACTER_ERR: Raised if the specified
+ * name contains an invalid character.
+ */
+ public Attr createAttributeNS(String namespaceURI, String qualifiedName,
+ String localpart)
+ throws DOMException {
+ return new AttrNSImpl(this, namespaceURI, qualifiedName, localpart);
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ * Returns a NodeList of all the Elements with a given local name and
+ * namespace URI in the order in which they would be encountered in a
+ * preorder traversal of the Document tree.
+ * @param namespaceURI The namespace URI of the elements to match
+ * on. The special value "*" matches all
+ * namespaces. When it is null or an empty
+ * string, this method behaves like
+ * getElementsByTagName.
+ * @param localName The local name of the elements to match on.
+ * The special value "*" matches all local names.
+ * @return NodeList A new NodeList object containing all the matched
+ * Elements.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public NodeList getElementsByTagNameNS(String namespaceURI,
+ String localName) {
+ return new DeepNodeListImpl(this, namespaceURI, localName);
+ }
+
+ //
+ // Object methods
+ //
+
+ /** Clone. */
+ public Object clone() throws CloneNotSupportedException {
+ CoreDocumentImpl newdoc = (CoreDocumentImpl) super.clone();
+ newdoc.docType = null;
+ newdoc.docElement = null;
+ return newdoc;
+ }
+
+ //
+ // Public static methods
+ //
+
+ /**
+ * Check the string against XML's definition of acceptable names for
+ * elements and attributes and so on using the XMLCharacterProperties
+ * utility class
+ */
+
+ public static final boolean isXMLName(String s, boolean xml11Version) {
+
+ if (s == null) {
+ return false;
+ }
+ if(!xml11Version)
+ return XMLChar.isValidName(s);
+ else
+ return XML11Char.isXML11ValidName(s);
+
+ } // isXMLName(String):boolean
+
+ /**
+ * Checks if the given qualified name is legal with respect
+ * to the version of XML to which this document must conform.
+ *
+ * @param prefix prefix of qualified name
+ * @param local local part of qualified name
+ */
+ public static final boolean isValidQName(String prefix, String local, boolean xml11Version) {
+
+ // check that both prefix and local part match NCName
+ if (local == null) return false;
+ boolean validNCName = false;
+
+ if (!xml11Version) {
+ validNCName = (prefix == null || XMLChar.isValidNCName(prefix))
+ && XMLChar.isValidNCName(local);
+ }
+ else {
+ validNCName = (prefix == null || XML11Char.isXML11ValidNCName(prefix))
+ && XML11Char.isXML11ValidNCName(local);
+ }
+
+ return validNCName;
+ }
+ //
+ // Protected methods
+ //
+
+ /**
+ * Uses the kidOK lookup table to check whether the proposed
+ * tree structure is legal.
+ */
+ protected boolean isKidOK(Node parent, Node child) {
+ if (allowGrammarAccess &&
+ parent.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+ return child.getNodeType() == Node.ELEMENT_NODE;
+ }
+ return 0 != (kidOK[parent.getNodeType()] & 1 << child.getNodeType());
+ }
+
+ /**
+ * Denotes that this node has changed.
+ */
+ protected void changed() {
+ changes++;
+ }
+
+ /**
+ * Returns the number of changes to this node.
+ */
+ protected int changes() {
+ return changes;
+ }
+
+ // NodeListCache pool
+
+ /**
+ * Returns a NodeListCache for the given node.
+ */
+ NodeListCache getNodeListCache(ParentNode owner) {
+ if (fFreeNLCache == null) {
+ return new NodeListCache(owner);
+ }
+ NodeListCache c = fFreeNLCache;
+ fFreeNLCache = fFreeNLCache.next;
+ c.fChild = null;
+ c.fChildIndex = -1;
+ c.fLength = -1;
+ // revoke previous ownership
+ if (c.fOwner != null) {
+ c.fOwner.fNodeListCache = null;
+ }
+ c.fOwner = owner;
+ // c.next = null; not necessary, except for confused people...
+ return c;
+ }
+
+ /**
+ * Puts the given NodeListCache in the free list.
+ * Note: The owner node can keep using it until we reuse it
+ */
+ void freeNodeListCache(NodeListCache c) {
+ c.next = fFreeNLCache;
+ fFreeNLCache = c;
+ }
+
+
+
+ /**
+ * Associate an object to a key on this node. The object can later be
+ * retrieved from this node by calling getUserData with the
+ * same key.
+ * @param n The node to associate the object to.
+ * @param key The key to associate the object to.
+ * @param data The object to associate to the given key, or
+ * null to remove any existing association to that key.
+ * @param handler The handler to associate to that key, or
+ * null .
+ * @return Returns the DOMObject previously associated to
+ * the given key on this node, or null if there was none.
+ * @since DOM Level 3
+ *
+ * REVISIT: we could use a free list of UserDataRecord here
+ */
+ public Object setUserData(Node n, String key,
+ Object data, UserDataHandler handler) {
+ if (data == null) {
+ if (userData != null) {
+ Hashtable t = (Hashtable) userData.get(n);
+ if (t != null) {
+ Object o = t.remove(key);
+ if (o != null) {
+ UserDataRecord r = (UserDataRecord) o;
+ return r.fData;
+ }
+ }
+ }
+ return null;
+ }
+ else {
+ Hashtable t;
+ if (userData == null) {
+ userData = new WeakHashMap();
+ t = new Hashtable();
+ userData.put(n, t);
+ }
+ else {
+ t = (Hashtable) userData.get(n);
+ if (t == null) {
+ t = new Hashtable();
+ userData.put(n, t);
+ }
+ }
+ Object o = t.put(key, new UserDataRecord(data, handler));
+ if (o != null) {
+ UserDataRecord r = (UserDataRecord) o;
+ return r.fData;
+ }
+ return null;
+ }
+ }
+
+
+ /**
+ * Retrieves the object associated to a key on a this node. The object
+ * must first have been set to this node by calling
+ * setUserData with the same key.
+ * @param n The node the object is associated to.
+ * @param key The key the object is associated to.
+ * @return Returns the DOMObject associated to the given key
+ * on this node, or null if there was none.
+ * @since DOM Level 3
+ */
+ public Object getUserData(Node n, String key) {
+ if (userData == null) {
+ return null;
+ }
+ Hashtable t = (Hashtable) userData.get(n);
+ if (t == null) {
+ return null;
+ }
+ Object o = t.get(key);
+ if (o != null) {
+ UserDataRecord r = (UserDataRecord) o;
+ return r.fData;
+ }
+ return null;
+ }
+
+ protected Hashtable getUserDataRecord(Node n){
+ if (userData == null) {
+ return null;
+ }
+ Hashtable t = (Hashtable) userData.get(n);
+ if (t == null) {
+ return null;
+ }
+ return t;
+ }
+
+ /**
+ * Remove user data table for the given node.
+ * @param n The node this operation applies to.
+ * @return The removed table.
+ */
+ Hashtable removeUserDataTable(Node n) {
+ if (userData == null) {
+ return null;
+ }
+ return (Hashtable) userData.get(n);
+ }
+
+ /**
+ * Set user data table for the given node.
+ * @param n The node this operation applies to.
+ * @param data The user data table.
+ */
+ void setUserDataTable(Node n, Hashtable data) {
+ if (userData == null) {
+ userData = new WeakHashMap();
+ }
+ if (data != null) {
+ userData.put(n, data);
+ }
+ }
+
+ /**
+ * Call user data handlers when a node is deleted (finalized)
+ * @param n The node this operation applies to.
+ * @param c The copy node or null.
+ * @param operation The operation - import, clone, or delete.
+ */
+ protected void callUserDataHandlers(Node n, Node c, short operation) {
+ if (userData == null) {
+ return;
+ }
+ //Hashtable t = (Hashtable) userData.get(n);
+ if(n instanceof NodeImpl){
+ Hashtable t = ((NodeImpl)n).getUserDataRecord();
+ if (t == null || t.isEmpty()) {
+ return;
+ }
+ callUserDataHandlers(n, c, operation,t);
+ }
+ }
+
+ /**
+ * Call user data handlers when a node is deleted (finalized)
+ * @param n The node this operation applies to.
+ * @param c The copy node or null.
+ * @param operation The operation - import, clone, or delete.
+ * @param handlers Data associated with n.
+ */
+ void callUserDataHandlers(Node n, Node c, short operation, Hashtable userData) {
+ if (userData == null || userData.isEmpty()) {
+ return;
+ }
+ Iterator entries = userData.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ String key = (String) entry.getKey();
+ UserDataRecord r = (UserDataRecord) entry.getValue();
+ if (r.fHandler != null) {
+ r.fHandler.handle(operation, key, r.fData, n, c);
+ }
+ }
+ }
+
+ /**
+ * Call user data handlers to let them know the nodes they are related to
+ * are being deleted. The alternative would be to do that on Node but
+ * because the nodes are used as the keys we have a reference to them that
+ * prevents them from being gc'ed until the document is. At the same time,
+ * doing it here has the advantage of avoiding a finalize() method on Node,
+ * which would affect all nodes and not just the ones that have a user
+ * data.
+ */
+ // Temporarily comment out this method, because
+ // 1. It seems that finalizers are not guaranteed to be called, so the
+ // functionality is not implemented.
+ // 2. It affects the performance greatly in multi-thread environment.
+ // -SG
+ /*public void finalize() {
+ if (userData == null) {
+ return;
+ }
+ Enumeration nodes = userData.keys();
+ while (nodes.hasMoreElements()) {
+ Object node = nodes.nextElement();
+ Hashtable t = (Hashtable) userData.get(node);
+ if (t != null && !t.isEmpty()) {
+ Enumeration keys = t.keys();
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+ UserDataRecord r = (UserDataRecord) t.get(key);
+ if (r.fHandler != null) {
+ r.fHandler.handle(UserDataHandler.NODE_DELETED,
+ key, r.fData, null, null);
+ }
+ }
+ }
+ }
+ }*/
+
+ protected final void checkNamespaceWF( String qname, int colon1,
+ int colon2) {
+
+ if (!errorChecking) {
+ return;
+ }
+ // it is an error for NCName to have more than one ':'
+ // check if it is valid QName [Namespace in XML production 6]
+ // :camera , nikon:camera:minolta, camera:
+ if (colon1 == 0 || colon1 == qname.length() - 1 || colon2 != colon1) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NAMESPACE_ERR",
+ null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ }
+ protected final void checkDOMNSErr(String prefix,
+ String namespace) {
+ if (errorChecking) {
+ if (namespace == null) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NAMESPACE_ERR",
+ null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ else if (prefix.equals("xml")
+ && !namespace.equals(NamespaceContext.XML_URI)) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NAMESPACE_ERR",
+ null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ else if (
+ prefix.equals("xmlns")
+ && !namespace.equals(NamespaceContext.XMLNS_URI)
+ || (!prefix.equals("xmlns")
+ && namespace.equals(NamespaceContext.XMLNS_URI))) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NAMESPACE_ERR",
+ null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ }
+ }
+
+ /**
+ * Checks if the given qualified name is legal with respect
+ * to the version of XML to which this document must conform.
+ *
+ * @param prefix prefix of qualified name
+ * @param local local part of qualified name
+ */
+ protected final void checkQName(String prefix, String local) {
+ if (!errorChecking) {
+ return;
+ }
+
+ // check that both prefix and local part match NCName
+ boolean validNCName = false;
+ if (!xml11Version) {
+ validNCName = (prefix == null || XMLChar.isValidNCName(prefix))
+ && XMLChar.isValidNCName(local);
+ }
+ else {
+ validNCName = (prefix == null || XML11Char.isXML11ValidNCName(prefix))
+ && XML11Char.isXML11ValidNCName(local);
+ }
+
+ if (!validNCName) {
+ // REVISIT: add qname parameter to the message
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "INVALID_CHARACTER_ERR",
+ null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ }
+
+ /**
+ * We could have more xml versions in future , but for now we could
+ * do with this to handle XML 1.0 and 1.1
+ */
+ boolean isXML11Version(){
+ return xml11Version;
+ }
+
+ boolean isNormalizeDocRequired(){
+ // REVISIT: Implement to optimize when normalization
+ // is required
+ return true;
+ }
+
+ //we should be checking the (elements, attribute, entity etc.) names only when
+ //version of the document is changed.
+ boolean isXMLVersionChanged(){
+ return xmlVersionChanged ;
+ }
+ /**
+ * NON-DOM: kept for backward compatibility
+ * Store user data related to a given node
+ * This is a place where we could use weak references! Indeed, the node
+ * here won't be GC'ed as long as some user data is attached to it, since
+ * the userData table will have a reference to the node.
+ */
+ protected void setUserData(NodeImpl n, Object data) {
+ setUserData(n, "XERCES1DOMUSERDATA", data, null);
+ }
+
+ /**
+ * NON-DOM: kept for backward compatibility
+ * Retreive user data related to a given node
+ */
+ protected Object getUserData(NodeImpl n) {
+ return getUserData(n, "XERCES1DOMUSERDATA");
+ }
+
+
+ // Event related methods overidden in subclass
+
+ protected void addEventListener(NodeImpl node, String type,
+ EventListener listener,
+ boolean useCapture) {
+ // does nothing by default - overidden in subclass
+ }
+
+ protected void removeEventListener(NodeImpl node, String type,
+ EventListener listener,
+ boolean useCapture) {
+ // does nothing by default - overidden in subclass
+ }
+
+ protected void copyEventListeners(NodeImpl src, NodeImpl tgt) {
+ // does nothing by default - overidden in subclass
+ }
+
+ protected boolean dispatchEvent(NodeImpl node, Event event) {
+ // does nothing by default - overidden in subclass
+ return false;
+ }
+
+ // Notification methods overidden in subclasses
+
+ /**
+ * A method to be called when some text was changed in a text node,
+ * so that live objects can be notified.
+ */
+ void replacedText(CharacterDataImpl node) {
+ }
+
+ /**
+ * A method to be called when some text was deleted from a text node,
+ * so that live objects can be notified.
+ */
+ void deletedText(CharacterDataImpl node, int offset, int count) {
+ }
+
+ /**
+ * A method to be called when some text was inserted into a text node,
+ * so that live objects can be notified.
+ */
+ void insertedText(CharacterDataImpl node, int offset, int count) {
+ }
+
+ /**
+ * A method to be called when a character data node is about to be modified
+ */
+ void modifyingCharacterData(NodeImpl node, boolean replace) {
+ }
+
+ /**
+ * A method to be called when a character data node has been modified
+ */
+ void modifiedCharacterData(NodeImpl node, String oldvalue, String value, boolean replace) {
+ }
+
+ /**
+ * A method to be called when a node is about to be inserted in the tree.
+ */
+ void insertingNode(NodeImpl node, boolean replace) {
+ }
+
+ /**
+ * A method to be called when a node has been inserted in the tree.
+ */
+ void insertedNode(NodeImpl node, NodeImpl newInternal, boolean replace) {
+ }
+
+ /**
+ * A method to be called when a node is about to be removed from the tree.
+ */
+ void removingNode(NodeImpl node, NodeImpl oldChild, boolean replace) {
+ }
+
+ /**
+ * A method to be called when a node has been removed from the tree.
+ */
+ void removedNode(NodeImpl node, boolean replace) {
+ }
+
+ /**
+ * A method to be called when a node is about to be replaced in the tree.
+ */
+ void replacingNode(NodeImpl node) {
+ }
+
+ /**
+ * A method to be called when a node has been replaced in the tree.
+ */
+ void replacedNode(NodeImpl node) {
+ }
+
+ /**
+ * A method to be called when a character data node is about to be replaced
+ */
+ void replacingData(NodeImpl node) {
+ }
+
+ /**
+ * method to be called when a character data node has been replaced.
+ */
+ void replacedCharacterData(NodeImpl node, String oldvalue, String value) {
+ }
+
+
+ /**
+ * A method to be called when an attribute value has been modified
+ */
+ void modifiedAttrValue(AttrImpl attr, String oldvalue) {
+ }
+
+ /**
+ * A method to be called when an attribute node has been set
+ */
+ void setAttrNode(AttrImpl attr, AttrImpl previous) {
+ }
+
+ /**
+ * A method to be called when an attribute node has been removed
+ */
+ void removedAttrNode(AttrImpl attr, NodeImpl oldOwner, String name) {
+ }
+
+ /**
+ * A method to be called when an attribute node has been renamed
+ */
+ void renamedAttrNode(Attr oldAt, Attr newAt) {
+ }
+
+ /**
+ * A method to be called when an element has been renamed
+ */
+ void renamedElement(Element oldEl, Element newEl) {
+ }
+
+ /**
+ * The serialized forms of the user data and node table
+ * maps are Hashtables. Convert them into WeakHashMaps
+ * on load.
+ */
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ if (userData != null) {
+ userData = new WeakHashMap(userData);
+ }
+ if (nodeTable != null) {
+ nodeTable = new WeakHashMap(nodeTable);
+ }
+ }
+
+ /**
+ * To allow DOM trees serialized by newer versions of Xerces
+ * to be read by older versions briefly move the user data
+ * and node table into Hashtables.
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ // Keep references to the original objects for restoration after serialization
+ final Map oldUserData = this.userData;
+ final Map oldNodeTable = this.nodeTable;
+ try {
+ if (oldUserData != null) {
+ this.userData = new Hashtable(oldUserData);
+ }
+ if (oldNodeTable != null) {
+ nodeTable = new Hashtable(oldNodeTable);
+ }
+ out.defaultWriteObject();
+ }
+ // If the write fails for some reason ensure
+ // that we restore the original objects.
+ finally {
+ this.userData = oldUserData;
+ this.nodeTable = oldNodeTable;
+ }
+ }
+
+} // class CoreDocumentImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DOMConfigurationImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DOMConfigurationImpl.java
new file mode 100644
index 0000000..8058dd7
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DOMConfigurationImpl.java
@@ -0,0 +1,1220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.impl.XMLEntityManager;
+import org.apache.xerces.impl.XMLErrorReporter;
+import org.apache.xerces.impl.dv.DTDDVFactory;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.impl.validation.ValidationManager;
+import org.apache.xerces.util.DOMEntityResolverWrapper;
+import org.apache.xerces.util.DOMErrorHandlerWrapper;
+import org.apache.xerces.util.MessageFormatter;
+import org.apache.xerces.util.ParserConfigurationSettings;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.xni.XMLDTDContentModelHandler;
+import org.apache.xerces.xni.XMLDTDHandler;
+import org.apache.xerces.xni.XMLDocumentHandler;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.grammars.XMLGrammarPool;
+import org.apache.xerces.xni.parser.XMLComponent;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+import org.apache.xerces.xni.parser.XMLErrorHandler;
+import org.apache.xerces.xni.parser.XMLInputSource;
+import org.apache.xerces.xni.parser.XMLParserConfiguration;
+import org.w3c.dom.DOMConfiguration;
+import org.w3c.dom.DOMErrorHandler;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMStringList;
+import org.w3c.dom.ls.LSResourceResolver;
+
+/**
+ * Xerces implementation of DOMConfiguration that maintains a table of recognized parameters.
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani, IBM
+ * @author Neeraj Bajaj, Sun Microsystems.
+ * @version $Id$
+ */
+public class DOMConfigurationImpl extends ParserConfigurationSettings
+ implements XMLParserConfiguration, DOMConfiguration {
+
+ //
+ // Constants
+ //
+
+ protected static final String XML11_DATATYPE_VALIDATOR_FACTORY =
+ "org.apache.xerces.impl.dv.dtd.XML11DTDDVFactoryImpl";
+
+ // feature identifiers
+
+ /** Feature identifier: validation. */
+ protected static final String XERCES_VALIDATION =
+ Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
+
+ /** Feature identifier: namespaces. */
+ protected static final String XERCES_NAMESPACES =
+ Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
+
+ protected static final String SCHEMA =
+ Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
+
+ protected static final String SCHEMA_FULL_CHECKING =
+ Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
+
+ protected static final String DYNAMIC_VALIDATION =
+ Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
+
+ protected static final String NORMALIZE_DATA =
+ Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
+
+ /** Feature identifier: send element default value via characters() */
+ protected static final String SCHEMA_ELEMENT_DEFAULT =
+ Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT;
+
+ /** sending psvi in the pipeline */
+ protected static final String SEND_PSVI =
+ Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI;
+
+ /** Feature: generate synthetic annotations */
+ protected static final String GENERATE_SYNTHETIC_ANNOTATIONS =
+ Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
+
+ /** Feature identifier: validate annotations */
+ protected static final String VALIDATE_ANNOTATIONS =
+ Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE;
+
+ /** Feature identifier: honour all schemaLocations */
+ protected static final String HONOUR_ALL_SCHEMALOCATIONS =
+ Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
+
+ /** Feature identifier: use grammar pool only */
+ protected static final String USE_GRAMMAR_POOL_ONLY =
+ Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE;
+
+ /** Feature identifier: load external DTD. */
+ protected static final String DISALLOW_DOCTYPE_DECL_FEATURE =
+ Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
+
+ /** Feature identifier: balance syntax trees. */
+ protected static final String BALANCE_SYNTAX_TREES =
+ Constants.XERCES_FEATURE_PREFIX + Constants.BALANCE_SYNTAX_TREES;
+
+ /** Feature identifier: warn on duplicate attribute definition. */
+ protected static final String WARN_ON_DUPLICATE_ATTDEF =
+ Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
+
+ /** Feature identifier: namespace growth */
+ protected static final String NAMESPACE_GROWTH =
+ Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE;
+
+ protected static final String TOLERATE_DUPLICATES =
+ Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE;
+ // property identifiers
+
+ /** Property identifier: entity manager. */
+ protected static final String ENTITY_MANAGER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
+
+ /** Property identifier: error reporter. */
+ protected static final String ERROR_REPORTER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
+
+ /** Property identifier: xml string. */
+ protected static final String XML_STRING =
+ Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY;
+
+ /** Property identifier: symbol table. */
+ protected static final String SYMBOL_TABLE =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
+
+ /** Property id: Grammar pool. */
+ protected static final String GRAMMAR_POOL =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
+
+ /** property identifier: security manager. */
+ protected static final String SECURITY_MANAGER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
+
+ /** Property identifier: error handler. */
+ protected static final String ERROR_HANDLER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
+
+ /** Property identifier: entity resolver. */
+ protected static final String ENTITY_RESOLVER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
+
+ /** Property identifier: JAXP schema language / DOM schema-type. */
+ protected static final String JAXP_SCHEMA_LANGUAGE =
+ Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
+
+ /** Property identifier: JAXP schema source/ DOM schema-location. */
+ protected static final String JAXP_SCHEMA_SOURCE =
+ Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
+
+ /** Property identifier: DTD validator. */
+ protected final static String DTD_VALIDATOR_PROPERTY =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
+
+ /** Property identifier: datatype validator factory. */
+ protected static final String DTD_VALIDATOR_FACTORY_PROPERTY =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
+
+ protected static final String VALIDATION_MANAGER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
+
+ /** Property identifier: schema location. */
+ protected static final String SCHEMA_LOCATION =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION;
+
+ /** Property identifier: no namespace schema location. */
+ protected static final String SCHEMA_NONS_LOCATION =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION;
+
+ /** Property identifier: Schema DV Factory */
+ protected static final String SCHEMA_DV_FACTORY =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY;
+
+ //
+ // Data
+ //
+ XMLDocumentHandler fDocumentHandler;
+
+ /** Normalization features*/
+ protected short features = 0;
+
+ protected final static short NAMESPACES = 0x1<<0;
+ protected final static short DTNORMALIZATION = 0x1<<1;
+ protected final static short ENTITIES = 0x1<<2;
+ protected final static short CDATA = 0x1<<3;
+ protected final static short SPLITCDATA = 0x1<<4;
+ protected final static short COMMENTS = 0x1<<5;
+ protected final static short VALIDATE = 0x1<<6;
+ protected final static short PSVI = 0x1<<7;
+ protected final static short WELLFORMED = 0x1<<8;
+ protected final static short NSDECL = 0x1<<9;
+
+ protected final static short INFOSET_TRUE_PARAMS = NAMESPACES | COMMENTS | WELLFORMED | NSDECL;
+ protected final static short INFOSET_FALSE_PARAMS = ENTITIES | DTNORMALIZATION | CDATA;
+ protected final static short INFOSET_MASK = INFOSET_TRUE_PARAMS | INFOSET_FALSE_PARAMS;
+
+ // components
+
+ /** Symbol table. */
+ protected SymbolTable fSymbolTable;
+
+ /** Components. */
+ protected ArrayList fComponents;
+
+ protected ValidationManager fValidationManager;
+
+ /** Locale. */
+ protected Locale fLocale;
+
+ /** Error reporter */
+ protected XMLErrorReporter fErrorReporter;
+
+ protected final DOMErrorHandlerWrapper fErrorHandlerWrapper =
+ new DOMErrorHandlerWrapper();
+
+ /** Current Datatype validator factory. */
+ protected DTDDVFactory fCurrentDVFactory;
+
+ /** The XML 1.0 Datatype validator factory. */
+ protected DTDDVFactory fDatatypeValidatorFactory;
+
+ /** The XML 1.1 Datatype validator factory. **/
+ protected DTDDVFactory fXML11DatatypeFactory;
+
+ // private data
+
+ private String fSchemaLocation = null;
+ private DOMStringList fRecognizedParameters;
+
+ //
+ // Constructors
+ //
+
+ /** Default Constructor. */
+ protected DOMConfigurationImpl() {
+ this(null, null);
+ } // ()
+
+ /**
+ * Constructs a parser configuration using the specified symbol table.
+ *
+ * @param symbolTable The symbol table to use.
+ */
+ protected DOMConfigurationImpl(SymbolTable symbolTable) {
+ this(symbolTable, null);
+ } // (SymbolTable)
+
+ /**
+ * Constructs a parser configuration using the specified symbol table
+ * and parent settings.
+ *
+ * @param symbolTable The symbol table to use.
+ * @param parentSettings The parent settings.
+ */
+ protected DOMConfigurationImpl(SymbolTable symbolTable,
+ XMLComponentManager parentSettings) {
+ super(parentSettings);
+
+ // create storage for recognized features and properties
+ fRecognizedFeatures = new ArrayList();
+ fRecognizedProperties = new ArrayList();
+
+ // create table for features and properties
+ fFeatures = new HashMap();
+ fProperties = new HashMap();
+
+ // add default recognized features
+ final String[] recognizedFeatures = {
+ XERCES_VALIDATION,
+ XERCES_NAMESPACES,
+ SCHEMA,
+ SCHEMA_FULL_CHECKING,
+ DYNAMIC_VALIDATION,
+ NORMALIZE_DATA,
+ SCHEMA_ELEMENT_DEFAULT,
+ SEND_PSVI,
+ GENERATE_SYNTHETIC_ANNOTATIONS,
+ VALIDATE_ANNOTATIONS,
+ HONOUR_ALL_SCHEMALOCATIONS,
+ USE_GRAMMAR_POOL_ONLY,
+ DISALLOW_DOCTYPE_DECL_FEATURE,
+ BALANCE_SYNTAX_TREES,
+ WARN_ON_DUPLICATE_ATTDEF,
+ PARSER_SETTINGS,
+ NAMESPACE_GROWTH,
+ TOLERATE_DUPLICATES
+ };
+ addRecognizedFeatures(recognizedFeatures);
+
+ // set state for default features
+ setFeature(XERCES_VALIDATION, false);
+ setFeature(SCHEMA, false);
+ setFeature(SCHEMA_FULL_CHECKING, false);
+ setFeature(DYNAMIC_VALIDATION, false);
+ setFeature(NORMALIZE_DATA, false);
+ setFeature(SCHEMA_ELEMENT_DEFAULT, false);
+ setFeature(XERCES_NAMESPACES, true);
+ setFeature(SEND_PSVI, true);
+ setFeature(GENERATE_SYNTHETIC_ANNOTATIONS, false);
+ setFeature(VALIDATE_ANNOTATIONS, false);
+ setFeature(HONOUR_ALL_SCHEMALOCATIONS, false);
+ setFeature(USE_GRAMMAR_POOL_ONLY, false);
+ setFeature(DISALLOW_DOCTYPE_DECL_FEATURE, false);
+ setFeature(BALANCE_SYNTAX_TREES, false);
+ setFeature(WARN_ON_DUPLICATE_ATTDEF, false);
+ setFeature(PARSER_SETTINGS, true);
+ setFeature(NAMESPACE_GROWTH, false);
+ setFeature(TOLERATE_DUPLICATES, false);
+
+ // add default recognized properties
+ final String[] recognizedProperties = {
+ XML_STRING,
+ SYMBOL_TABLE,
+ ERROR_HANDLER,
+ ENTITY_RESOLVER,
+ ERROR_REPORTER,
+ ENTITY_MANAGER,
+ VALIDATION_MANAGER,
+ GRAMMAR_POOL,
+ SECURITY_MANAGER,
+ JAXP_SCHEMA_SOURCE,
+ JAXP_SCHEMA_LANGUAGE,
+ SCHEMA_LOCATION,
+ SCHEMA_NONS_LOCATION,
+ DTD_VALIDATOR_PROPERTY,
+ DTD_VALIDATOR_FACTORY_PROPERTY,
+ SCHEMA_DV_FACTORY
+ };
+ addRecognizedProperties(recognizedProperties);
+
+ // set default values for normalization features
+ features |= NAMESPACES;
+ features |= ENTITIES;
+ features |= COMMENTS;
+ features |= CDATA;
+ features |= SPLITCDATA;
+ features |= WELLFORMED;
+ features |= NSDECL;
+
+ if (symbolTable == null) {
+ symbolTable = new SymbolTable();
+ }
+ fSymbolTable = symbolTable;
+
+ fComponents = new ArrayList();
+
+ setProperty(SYMBOL_TABLE, fSymbolTable);
+ fErrorReporter = new XMLErrorReporter();
+ setProperty(ERROR_REPORTER, fErrorReporter);
+ addComponent(fErrorReporter);
+
+ fDatatypeValidatorFactory = DTDDVFactory.getInstance();
+ fXML11DatatypeFactory = DTDDVFactory.getInstance(XML11_DATATYPE_VALIDATOR_FACTORY);
+ fCurrentDVFactory = fDatatypeValidatorFactory;
+ setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, fCurrentDVFactory);
+
+ XMLEntityManager manager = new XMLEntityManager();
+ setProperty(ENTITY_MANAGER, manager);
+ addComponent(manager);
+
+ fValidationManager = createValidationManager();
+ setProperty(VALIDATION_MANAGER, fValidationManager);
+
+
+ // add message formatters
+ if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
+ XMLMessageFormatter xmft = new XMLMessageFormatter();
+ fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
+ fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
+ }
+
+ // REVISIT: try to include XML Schema formatter.
+ // This is a hack to allow DTD configuration to be build.
+ //
+ if (fErrorReporter.getMessageFormatter("http://www.w3.org/TR/xml-schema-1") == null) {
+ MessageFormatter xmft = null;
+ try {
+ xmft = (MessageFormatter)(
+ ObjectFactory.newInstance("org.apache.xerces.impl.xs.XSMessageFormatter",
+ ObjectFactory.findClassLoader(), true));
+ } catch (Exception exception){
+ }
+
+ if (xmft != null) {
+ fErrorReporter.putMessageFormatter("http://www.w3.org/TR/xml-schema-1", xmft);
+ }
+ }
+
+
+ // set locale
+ try {
+ setLocale(Locale.getDefault());
+ }
+ catch (XNIException e) {
+ // do nothing
+ // REVISIT: What is the right thing to do? -Ac
+ }
+
+
+ } // (SymbolTable)
+
+
+ //
+ // XMLParserConfiguration methods
+ //
+
+ /**
+ * Parse an XML document.
+ *
+ * The parser can use this method to instruct this configuration
+ * to begin parsing an XML document from any valid input source
+ * (a character stream, a byte stream, or a URI).
+ *
+ * Parsers may not invoke this method while a parse is in progress.
+ * Once a parse is complete, the parser may then parse another XML
+ * document.
+ *
+ * This method is synchronous: it will not return until parsing
+ * has ended. If a client application wants to terminate
+ * parsing early, it should throw an exception.
+ *
+ * @param inputSource The input source for the top-level of the
+ * XML document.
+ *
+ * @exception XNIException Any XNI exception, possibly wrapping
+ * another exception.
+ * @exception IOException An IO exception from the parser, possibly
+ * from a byte stream or character stream
+ * supplied by the parser.
+ */
+ public void parse(XMLInputSource inputSource)
+ throws XNIException, IOException{
+ // no-op
+ }
+
+ /**
+ * Sets the document handler on the last component in the pipeline
+ * to receive information about the document.
+ *
+ * @param documentHandler The document handler.
+ */
+ public void setDocumentHandler(XMLDocumentHandler documentHandler) {
+ fDocumentHandler = documentHandler;
+ } // setDocumentHandler(XMLDocumentHandler)
+
+ /** Returns the registered document handler. */
+ public XMLDocumentHandler getDocumentHandler() {
+ return fDocumentHandler;
+ } // getDocumentHandler():XMLDocumentHandler
+
+ /**
+ * Sets the DTD handler.
+ *
+ * @param dtdHandler The DTD handler.
+ */
+ public void setDTDHandler(XMLDTDHandler dtdHandler) {
+ //no-op
+ } // setDTDHandler(XMLDTDHandler)
+
+ /** Returns the registered DTD handler. */
+ public XMLDTDHandler getDTDHandler() {
+ return null;
+ } // getDTDHandler():XMLDTDHandler
+
+ /**
+ * Sets the DTD content model handler.
+ *
+ * @param handler The DTD content model handler.
+ */
+ public void setDTDContentModelHandler(XMLDTDContentModelHandler handler) {
+ //no-op
+
+ } // setDTDContentModelHandler(XMLDTDContentModelHandler)
+
+ /** Returns the registered DTD content model handler. */
+ public XMLDTDContentModelHandler getDTDContentModelHandler() {
+ return null;
+ } // getDTDContentModelHandler():XMLDTDContentModelHandler
+
+ /**
+ * Sets the resolver used to resolve external entities. The EntityResolver
+ * interface supports resolution of public and system identifiers.
+ *
+ * @param resolver The new entity resolver. Passing a null value will
+ * uninstall the currently installed resolver.
+ */
+ public void setEntityResolver(XMLEntityResolver resolver) {
+ fProperties.put(ENTITY_RESOLVER, resolver);
+ } // setEntityResolver(XMLEntityResolver)
+
+ /**
+ * Return the current entity resolver.
+ *
+ * @return The current entity resolver, or null if none
+ * has been registered.
+ * @see #setEntityResolver
+ */
+ public XMLEntityResolver getEntityResolver() {
+ return (XMLEntityResolver)fProperties.get(ENTITY_RESOLVER);
+ } // getEntityResolver():XMLEntityResolver
+
+ /**
+ * Allow an application to register an error event handler.
+ *
+ * If the application does not register an error handler, all
+ * error events reported by the SAX parser will be silently
+ * ignored; however, normal processing may not continue. It is
+ * highly recommended that all SAX applications implement an
+ * error handler to avoid unexpected bugs.
+ *
+ * Applications may register a new or different handler in the
+ * middle of a parse, and the SAX parser must begin using the new
+ * handler immediately.
+ *
+ * @param errorHandler The error handler.
+ * @exception java.lang.NullPointerException If the handler
+ * argument is null.
+ * @see #getErrorHandler
+ */
+ public void setErrorHandler(XMLErrorHandler errorHandler) {
+ if (errorHandler != null) {
+ fProperties.put(ERROR_HANDLER, errorHandler);
+ }
+ } // setErrorHandler(XMLErrorHandler)
+
+ /**
+ * Return the current error handler.
+ *
+ * @return The current error handler, or null if none
+ * has been registered.
+ * @see #setErrorHandler
+ */
+ public XMLErrorHandler getErrorHandler() {
+ return (XMLErrorHandler)fProperties.get(ERROR_HANDLER);
+ } // getErrorHandler():XMLErrorHandler
+
+ /**
+ * Returns the state of a feature.
+ *
+ * @param featureId The feature identifier.
+ * @return true if the feature is supported
+ *
+ * @throws XMLConfigurationException Thrown for configuration error.
+ * In general, components should
+ * only throw this exception if
+ * it is really
+ * a critical error.
+ */
+ public boolean getFeature(String featureId)
+ throws XMLConfigurationException {
+ if (featureId.equals(PARSER_SETTINGS)) {
+ return true;
+ }
+ return super.getFeature(featureId);
+ }
+
+ /**
+ * Set the state of a feature.
+ *
+ * Set the state of any feature in a SAX2 parser. The parser
+ * might not recognize the feature, and if it does recognize
+ * it, it might not be able to fulfill the request.
+ *
+ * @param featureId The unique identifier (URI) of the feature.
+ * @param state The requested state of the feature (true or false).
+ *
+ * @exception org.apache.xerces.xni.parser.XMLConfigurationException If the
+ * requested feature is not known.
+ */
+ public void setFeature(String featureId, boolean state)
+ throws XMLConfigurationException {
+
+ // save state if noone "objects"
+ super.setFeature(featureId, state);
+
+ } // setFeature(String,boolean)
+
+ /**
+ * setProperty
+ *
+ * @param propertyId
+ * @param value
+ */
+ public void setProperty(String propertyId, Object value)
+ throws XMLConfigurationException {
+
+ // store value if noone "objects"
+ super.setProperty(propertyId, value);
+
+ } // setProperty(String,Object)
+
+ /**
+ * Set the locale to use for messages.
+ *
+ * @param locale The locale object to use for localization of messages.
+ *
+ * @exception XNIException Thrown if the parser does not support the
+ * specified locale.
+ */
+ public void setLocale(Locale locale) throws XNIException {
+ fLocale = locale;
+ fErrorReporter.setLocale(locale);
+
+ } // setLocale(Locale)
+
+ /** Returns the locale. */
+ public Locale getLocale() {
+ return fLocale;
+ } // getLocale():Locale
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * setParameter
+ */
+ public void setParameter(String name, Object value) throws DOMException {
+ boolean found = true;
+
+ // REVISIT: Recognizes DOM L3 default features only.
+ // Does not yet recognize Xerces features.
+ if(value instanceof Boolean){
+ boolean state = ((Boolean)value).booleanValue();
+
+ if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
+ features = (short) (state ? features | COMMENTS : features & ~COMMENTS);
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
+ setFeature(NORMALIZE_DATA, state);
+ features =
+ (short) (state ? features | DTNORMALIZATION : features & ~DTNORMALIZATION);
+ if (state) {
+ features = (short) (features | VALIDATE);
+ }
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
+ features = (short) (state ? features | NAMESPACES : features & ~NAMESPACES);
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
+ features = (short) (state ? features | CDATA : features & ~CDATA);
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)) {
+ features = (short) (state ? features | ENTITIES : features & ~ENTITIES);
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
+ features = (short) (state ? features | SPLITCDATA : features & ~SPLITCDATA);
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_VALIDATE)) {
+ features = (short) (state ? features | VALIDATE : features & ~VALIDATE);
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
+ features = (short) (state ? features | WELLFORMED : features & ~WELLFORMED );
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
+ features = (short) (state ? features | NSDECL : features & ~NSDECL);
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_INFOSET)) {
+ // Setting to false has no effect.
+ if (state) {
+ features = (short) (features | INFOSET_TRUE_PARAMS);
+ features = (short) (features & ~INFOSET_FALSE_PARAMS);
+ setFeature(NORMALIZE_DATA, false);
+ }
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
+ || name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
+ || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
+ || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
+ ) {
+ if (state) { // true is not supported
+ throw newFeatureNotSupportedError(name);
+ }
+ }
+ else if ( name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
+ if (!state) { // false is not supported
+ throw newFeatureNotSupportedError(name);
+ }
+ }
+ else if (name.equalsIgnoreCase(SEND_PSVI) ){
+ // REVISIT: turning augmentation of PSVI is not support,
+ // because in this case we won't be able to retrieve element
+ // default value.
+ if (!state) { // false is not supported
+ throw newFeatureNotSupportedError(name);
+ }
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_PSVI)){
+ features = (short) (state ? features | PSVI : features & ~PSVI);
+ }
+ else {
+ found = false;
+ /*
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "FEATURE_NOT_FOUND",
+ new Object[] { name });
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ */
+ }
+
+ }
+
+ if (!found || !(value instanceof Boolean)) { // set properties
+ found = true;
+
+ if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
+ if (value instanceof DOMErrorHandler || value == null) {
+ fErrorHandlerWrapper.setErrorHandler((DOMErrorHandler)value);
+ setErrorHandler(fErrorHandlerWrapper);
+ }
+ else {
+ throw newTypeMismatchError(name);
+ }
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)) {
+ if (value instanceof LSResourceResolver || value == null) {
+ try {
+ setEntityResolver(new DOMEntityResolverWrapper((LSResourceResolver) value));
+ }
+ catch (XMLConfigurationException e) {}
+ }
+ else {
+ throw newTypeMismatchError(name);
+ }
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
+ if (value instanceof String || value == null) {
+ try {
+ if (value == null) {
+ fSchemaLocation = null;
+ setProperty (
+ Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
+ null);
+ }
+ else {
+ fSchemaLocation = (String) value;
+ // map DOM schema-location to JAXP schemaSource property
+ // tokenize location string
+ StringTokenizer t = new StringTokenizer(fSchemaLocation, " \n\t\r");
+ if (t.hasMoreTokens()) {
+ ArrayList locations = new ArrayList();
+ locations.add(t.nextToken());
+ while (t.hasMoreTokens()) {
+ locations.add (t.nextToken());
+ }
+ setProperty (
+ Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
+ locations.toArray(new String[locations.size()]));
+ }
+ else {
+ setProperty (
+ Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
+ new String [] {(String) value});
+ }
+ }
+ }
+ catch (XMLConfigurationException e) {}
+ }
+ else {
+ throw newTypeMismatchError(name);
+ }
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
+ if (value instanceof String || value == null) {
+ try {
+ if (value == null) {
+ setProperty(
+ Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
+ null);
+ }
+ else if (value.equals(Constants.NS_XMLSCHEMA)) {
+ // REVISIT: when add support to DTD validation
+ setProperty(
+ Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
+ Constants.NS_XMLSCHEMA);
+ }
+ else if (value.equals(Constants.NS_DTD)) {
+ // Added support for revalidation against DTDs
+ setProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
+ Constants.NS_DTD);
+ }
+ }
+ catch (XMLConfigurationException e) {}
+ }
+ else {
+ throw newTypeMismatchError(name);
+ }
+ }
+ else if (name.equalsIgnoreCase(ENTITY_RESOLVER)) {
+ if (value instanceof XMLEntityResolver || value == null) {
+ try {
+ setEntityResolver((XMLEntityResolver) value);
+ }
+ catch (XMLConfigurationException e) {}
+ }
+ else {
+ throw newTypeMismatchError(name);
+ }
+ }
+ else if (name.equalsIgnoreCase(SYMBOL_TABLE)) {
+ // Xerces Symbol Table
+ if (value instanceof SymbolTable){
+ setProperty(SYMBOL_TABLE, value);
+ }
+ else {
+ throw newTypeMismatchError(name);
+ }
+ }
+ else if (name.equalsIgnoreCase (GRAMMAR_POOL)) {
+ if (value instanceof XMLGrammarPool || value == null) {
+ setProperty(GRAMMAR_POOL, value);
+ }
+ else {
+ throw newTypeMismatchError(name);
+ }
+ }
+ else if (name.equalsIgnoreCase (SECURITY_MANAGER)) {
+ if (value instanceof org.apache.xerces.util.SecurityManager || value == null) {
+ setProperty(SECURITY_MANAGER, value);
+ }
+ else {
+ throw newTypeMismatchError(name);
+ }
+ }
+ else {
+ // REVISIT: check if this is a boolean parameter -- type mismatch should be thrown.
+ //parameter is not recognized
+ throw newFeatureNotFoundError(name);
+ }
+ }
+ }
+
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * getParameter
+ */
+ public Object getParameter(String name) throws DOMException {
+
+ // REVISIT: Recognizes DOM L3 default features only.
+ // Does not yet recognize Xerces features.
+
+ if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
+ return ((features & COMMENTS) != 0) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
+ return (features & NAMESPACES) != 0 ? Boolean.TRUE : Boolean.FALSE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
+ // REVISIT: datatype-normalization only takes effect if validation is on
+ return (features & DTNORMALIZATION) != 0 ? Boolean.TRUE : Boolean.FALSE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
+ return (features & CDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)) {
+ return (features & ENTITIES) != 0 ? Boolean.TRUE : Boolean.FALSE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
+ return (features & SPLITCDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_VALIDATE)) {
+ return (features & VALIDATE) != 0 ? Boolean.TRUE : Boolean.FALSE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
+ return (features & WELLFORMED) != 0 ? Boolean.TRUE : Boolean.FALSE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
+ return (features & NSDECL) != 0 ? Boolean.TRUE : Boolean.FALSE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_INFOSET)) {
+ return (features & INFOSET_MASK) == INFOSET_TRUE_PARAMS ? Boolean.TRUE : Boolean.FALSE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
+ || name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
+ || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
+ || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
+ ) {
+ return Boolean.FALSE;
+ }
+ else if (name.equalsIgnoreCase(SEND_PSVI)) {
+ return Boolean.TRUE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_PSVI)) {
+ return (features & PSVI) != 0 ? Boolean.TRUE : Boolean.FALSE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
+ return Boolean.TRUE;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
+ return fErrorHandlerWrapper.getErrorHandler();
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)) {
+ XMLEntityResolver entityResolver = getEntityResolver();
+ if (entityResolver != null && entityResolver instanceof DOMEntityResolverWrapper) {
+ return ((DOMEntityResolverWrapper) entityResolver).getEntityResolver();
+ }
+ return null;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
+ return getProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE);
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
+ return fSchemaLocation;
+ }
+ else if (name.equalsIgnoreCase(ENTITY_RESOLVER)) {
+ return getEntityResolver();
+ }
+ else if (name.equalsIgnoreCase(SYMBOL_TABLE)) {
+ return getProperty(SYMBOL_TABLE);
+ }
+ else if (name.equalsIgnoreCase(GRAMMAR_POOL)) {
+ return getProperty(GRAMMAR_POOL);
+ }
+ else if (name.equalsIgnoreCase(SECURITY_MANAGER)) {
+ return getProperty(SECURITY_MANAGER);
+ }
+ else {
+ throw newFeatureNotFoundError(name);
+ }
+ }
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * Check if setting a parameter to a specific value is supported.
+ *
+ * @param name The name of the parameter to check.
+ *
+ * @param value An object. if null, the returned value is true.
+ *
+ * @return true if the parameter could be successfully set to the
+ * specified value, or false if the parameter is not recognized or
+ * the requested value is not supported. This does not change the
+ * current value of the parameter itself.
+ */
+ public boolean canSetParameter(String name, Object value) {
+
+ if (value == null){
+ //if null, the returned value is true.
+ //REVISIT: I dont like this --- even for unrecognized parameter it would
+ //return 'true'. I think it should return false in that case.
+ // Application will be surprised to find that setParameter throws not
+ //recognized exception when canSetParameter returns 'true' Then what is the use
+ //of having canSetParameter ??? - nb.
+ return true ;
+ }
+ if( value instanceof Boolean ){
+ //features whose parameter value can be set either 'true' or 'false'
+ // or they accept any boolean value -- so we just need to check that
+ // its a boolean value..
+ if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)
+ || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)
+ || name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)
+ || name.equalsIgnoreCase(Constants.DOM_ENTITIES)
+ || name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)
+ || name.equalsIgnoreCase(Constants.DOM_NAMESPACES)
+ || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
+ || name.equalsIgnoreCase(Constants.DOM_WELLFORMED)
+ || name.equalsIgnoreCase(Constants.DOM_INFOSET)
+ || name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)
+ ) {
+ return true;
+ }//features whose parameter value can not be set to 'true'
+ else if (
+ name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
+ || name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
+ || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
+ || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
+ ) {
+ return (value.equals(Boolean.TRUE)) ? false : true;
+ }//features whose parameter value can not be set to 'false'
+ else if( name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
+ || name.equalsIgnoreCase(SEND_PSVI)
+ ) {
+ return (value.equals(Boolean.TRUE)) ? true : false;
+ }// if name is not among the above listed above -- its not recognized. return false
+ else {
+ return false ;
+ }
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
+ return (value instanceof DOMErrorHandler) ? true : false ;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)) {
+ return (value instanceof LSResourceResolver) ? true : false ;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
+ return (value instanceof String) ? true : false ;
+ }
+ else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
+ // REVISIT: should null value be supported?
+ // as of now we are only supporting W3C XML Schema and DTD.
+ return ((value instanceof String) &&
+ (value.equals(Constants.NS_XMLSCHEMA) || value.equals(Constants.NS_DTD))) ? true : false;
+ }
+ else if (name.equalsIgnoreCase(ENTITY_RESOLVER)) {
+ return (value instanceof XMLEntityResolver) ? true : false;
+ }
+ else if (name.equalsIgnoreCase(SYMBOL_TABLE)) {
+ // Xerces Symbol Table
+ return (value instanceof SymbolTable) ? true : false;
+ }
+ else if (name.equalsIgnoreCase (GRAMMAR_POOL)) {
+ return (value instanceof XMLGrammarPool) ? true : false;
+ }
+ else if (name.equalsIgnoreCase(SECURITY_MANAGER)) {
+ return (value instanceof org.apache.xerces.util.SecurityManager) ? true : false;
+ }
+ else {
+ //false if the parameter is not recognized or the requested value is not supported.
+ return false ;
+ }
+
+ } //canSetParameter
+
+ /**
+ * DOM Level 3 CR - Experimental.
+ *
+ * The list of the parameters supported by this
+ * DOMConfiguration object and for which at least one value
+ * can be set by the application. Note that this list can also contain
+ * parameter names defined outside this specification.
+ */
+ public DOMStringList getParameterNames() {
+ if (fRecognizedParameters == null){
+ ArrayList parameters = new ArrayList();
+
+ //Add DOM recognized parameters
+ //REVISIT: Would have been nice to have a list of
+ //recognized paramters.
+ parameters.add(Constants.DOM_COMMENTS);
+ parameters.add(Constants.DOM_DATATYPE_NORMALIZATION);
+ parameters.add(Constants.DOM_CDATA_SECTIONS);
+ parameters.add(Constants.DOM_ENTITIES);
+ parameters.add(Constants.DOM_SPLIT_CDATA);
+ parameters.add(Constants.DOM_NAMESPACES);
+ parameters.add(Constants.DOM_VALIDATE);
+
+ parameters.add(Constants.DOM_INFOSET);
+ parameters.add(Constants.DOM_NORMALIZE_CHARACTERS);
+ parameters.add(Constants.DOM_CANONICAL_FORM);
+ parameters.add(Constants.DOM_VALIDATE_IF_SCHEMA);
+ parameters.add(Constants.DOM_CHECK_CHAR_NORMALIZATION);
+ parameters.add(Constants.DOM_WELLFORMED);
+
+ parameters.add(Constants.DOM_NAMESPACE_DECLARATIONS);
+ parameters.add(Constants.DOM_ELEMENT_CONTENT_WHITESPACE);
+
+ parameters.add(Constants.DOM_ERROR_HANDLER);
+ parameters.add(Constants.DOM_SCHEMA_TYPE);
+ parameters.add(Constants.DOM_SCHEMA_LOCATION);
+ parameters.add(Constants.DOM_RESOURCE_RESOLVER);
+
+ //Add recognized xerces features and properties
+ parameters.add(ENTITY_RESOLVER);
+ parameters.add(GRAMMAR_POOL);
+ parameters.add(SECURITY_MANAGER);
+ parameters.add(SYMBOL_TABLE);
+ parameters.add(SEND_PSVI);
+
+ fRecognizedParameters = new DOMStringListImpl(parameters);
+
+ }
+
+ return fRecognizedParameters;
+ }//getParameterNames
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * reset all components before parsing
+ */
+ protected void reset() throws XNIException {
+
+ if (fValidationManager != null)
+ fValidationManager.reset();
+
+ int count = fComponents.size();
+ for (int i = 0; i < count; i++) {
+ XMLComponent c = (XMLComponent) fComponents.get(i);
+ c.reset(this);
+ }
+
+ } // reset()
+
+ /**
+ * Check a property. If the property is known and supported, this method
+ * simply returns. Otherwise, the appropriate exception is thrown.
+ *
+ * @param propertyId The unique identifier (URI) of the property
+ * being set.
+ * @exception org.apache.xerces.xni.parser.XMLConfigurationException If the
+ * requested feature is not known or supported.
+ */
+ protected void checkProperty(String propertyId)
+ throws XMLConfigurationException {
+
+ // special cases
+ if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
+ final int suffixLength = propertyId.length() - Constants.SAX_PROPERTY_PREFIX.length();
+
+ //
+ // http://xml.org/sax/properties/xml-string
+ // Value type: String
+ // Access: read-only
+ // Get the literal string of characters associated with the
+ // current event. If the parser recognises and supports this
+ // property but is not currently parsing text, it should return
+ // null (this is a good way to check for availability before the
+ // parse begins).
+ //
+ if (suffixLength == Constants.XML_STRING_PROPERTY.length() &&
+ propertyId.endsWith(Constants.XML_STRING_PROPERTY)) {
+ // REVISIT - we should probably ask xml-dev for a precise
+ // definition of what this is actually supposed to return, and
+ // in exactly which circumstances.
+ short type = XMLConfigurationException.NOT_SUPPORTED;
+ throw new XMLConfigurationException(type, propertyId);
+ }
+ }
+
+ // check property
+ super.checkProperty(propertyId);
+
+ } // checkProperty(String)
+
+
+ protected void addComponent(XMLComponent component) {
+
+ // don't add a component more than once
+ if (fComponents.contains(component)) {
+ return;
+ }
+ fComponents.add(component);
+
+ // register component's recognized features
+ String[] recognizedFeatures = component.getRecognizedFeatures();
+ addRecognizedFeatures(recognizedFeatures);
+
+ // register component's recognized properties
+ String[] recognizedProperties = component.getRecognizedProperties();
+ addRecognizedProperties(recognizedProperties);
+
+ } // addComponent(XMLComponent)
+
+ protected ValidationManager createValidationManager(){
+ return new ValidationManager();
+ }
+
+ protected final void setDTDValidatorFactory(String version) {
+ if ("1.1".equals(version)) {
+ if (fCurrentDVFactory != fXML11DatatypeFactory) {
+ fCurrentDVFactory = fXML11DatatypeFactory;
+ setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, fCurrentDVFactory);
+ }
+ }
+ else if (fCurrentDVFactory != fDatatypeValidatorFactory) {
+ fCurrentDVFactory = fDatatypeValidatorFactory;
+ setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, fCurrentDVFactory);
+ }
+ }
+
+ private static DOMException newFeatureNotSupportedError(String name) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "FEATURE_NOT_SUPPORTED",
+ new Object[] { name });
+ return new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ private static DOMException newFeatureNotFoundError(String name) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "FEATURE_NOT_FOUND",
+ new Object[] { name });
+ return new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+
+ private static DOMException newTypeMismatchError(String name) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "TYPE_MISMATCH_ERR",
+ new Object[] { name });
+ return new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
+ }
+
+} // class DOMConfigurationImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DOMErrorImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DOMErrorImpl.java
new file mode 100644
index 0000000..d9aa461
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DOMErrorImpl.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.apache.xerces.xni.parser.XMLParseException;
+import org.w3c.dom.DOMError;
+import org.w3c.dom.DOMLocator;
+
+
+/**
+ * DOMErrorImpl is an implementation that describes an error.
+ * Note: The error object that describes the error
+ * might be reused by Xerces implementation, across multiple calls to the
+ * handleEvent method on DOMErrorHandler interface.
+ *
+ *
+ * See also the Document Object Model (DOM) Level 3 Core Specification.
+ *
+ * @xerces.internal
+ *
+ * @author Gopal Sharma, SUN Microsystems Inc.
+ * @author Elena Litani, IBM
+ *
+ * @version $Id$
+ */
+
+// REVISIT: the implementation of ErrorReporter.
+// we probably should not pass XMLParseException
+//
+
+public class DOMErrorImpl implements DOMError {
+
+ //
+ // Data
+ //
+
+ public short fSeverity = DOMError.SEVERITY_WARNING;
+ public String fMessage = null;
+ public DOMLocatorImpl fLocator = new DOMLocatorImpl();
+ public Exception fException = null;
+ public String fType;
+ public Object fRelatedData;
+
+
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public DOMErrorImpl () {
+ }
+
+ /** Exctracts information from XMLParserException) */
+ public DOMErrorImpl (short severity, XMLParseException exception) {
+ fSeverity = severity;
+ fException = exception;
+ fLocator = createDOMLocator (exception);
+ }
+
+ /**
+ * The severity of the error, either SEVERITY_WARNING ,
+ * SEVERITY_ERROR , or SEVERITY_FATAL_ERROR .
+ */
+
+ public short getSeverity() {
+ return fSeverity;
+ }
+
+ /**
+ * An implementation specific string describing the error that occured.
+ */
+
+ public String getMessage() {
+ return fMessage;
+ }
+
+ /**
+ * The location of the error.
+ */
+
+ public DOMLocator getLocation() {
+ return fLocator;
+ }
+
+ // method to get the DOMLocator Object
+ private DOMLocatorImpl createDOMLocator(XMLParseException exception) {
+ // assuming DOMLocator wants the *expanded*, not the literal, URI of the doc... - neilg
+ return new DOMLocatorImpl(exception.getLineNumber(),
+ exception.getColumnNumber(),
+ exception.getCharacterOffset(),
+ exception.getExpandedSystemId());
+ } // createDOMLocator()
+
+
+ /**
+ * The related platform dependent exception if any.exception is a reserved
+ * word, we need to rename it.Change to "relatedException". (F2F 26 Sep
+ * 2001)
+ */
+ public Object getRelatedException(){
+ return fException;
+ }
+
+ public void reset(){
+ fSeverity = DOMError.SEVERITY_WARNING;
+ fException = null;
+ }
+
+ public String getType(){
+ return fType;
+ }
+
+ public Object getRelatedData(){
+ return fRelatedData;
+ }
+
+
+}// class DOMErrorImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DOMImplementationImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DOMImplementationImpl.java
new file mode 100644
index 0000000..d4fa6f6
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DOMImplementationImpl.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.DocumentType;
+
+/**
+ * The DOMImplementation class is description of a particular
+ * implementation of the Document Object Model. As such its data is
+ * static, shared by all instances of this implementation.
+ *
+ * The DOM API requires that it be a real object rather than static
+ * methods. However, there's nothing that says it can't be a singleton,
+ * so that's how I've implemented it.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DOMImplementationImpl extends CoreDOMImplementationImpl
+ implements DOMImplementation {
+
+ //
+ // Data
+ //
+
+ // static
+
+ /** Dom implementation singleton. */
+ static final DOMImplementationImpl singleton = new DOMImplementationImpl();
+
+
+ //
+ // Public methods
+ //
+
+ /** NON-DOM: Obtain and return the single shared object */
+ public static DOMImplementation getDOMImplementation() {
+ return singleton;
+ }
+
+ //
+ // DOMImplementation methods
+ //
+
+ /**
+ * Test if the DOM implementation supports a specific "feature" --
+ * currently meaning language and level thereof.
+ *
+ * @param feature The package name of the feature to test.
+ * In Level 1, supported values are "HTML" and "XML" (case-insensitive).
+ * At this writing, org.apache.xerces.dom supports only XML.
+ *
+ * @param version The version number of the feature being tested.
+ * This is interpreted as "Version of the DOM API supported for the
+ * specified Feature", and in Level 1 should be "1.0"
+ *
+ * @return true iff this implementation is compatable with the
+ * specified feature and version.
+ */
+ public boolean hasFeature(String feature, String version) {
+
+ boolean result = super.hasFeature(feature, version);
+ if (!result) {
+ boolean anyVersion = version == null || version.length() == 0;
+ if (feature.startsWith("+")) {
+ feature = feature.substring(1);
+ }
+ return (
+ (feature.equalsIgnoreCase("Events")
+ && (anyVersion || version.equals("2.0")))
+ || (feature.equalsIgnoreCase("MutationEvents")
+ && (anyVersion || version.equals("2.0")))
+ || (feature.equalsIgnoreCase("Traversal")
+ && (anyVersion || version.equals("2.0")))
+ || (feature.equalsIgnoreCase("Range")
+ && (anyVersion || version.equals("2.0")))
+ || (feature.equalsIgnoreCase("MutationEvents")
+ && (anyVersion || version.equals("2.0"))));
+ }
+ return result;
+ } // hasFeature(String,String):boolean
+
+ //
+ // Protected methods
+ //
+
+ protected CoreDocumentImpl createDocument(DocumentType doctype) {
+ return new DocumentImpl(doctype);
+ }
+
+} // class DOMImplementationImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DOMImplementationListImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DOMImplementationListImpl.java
new file mode 100644
index 0000000..ef54e12
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DOMImplementationListImpl.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.DOMImplementationList;
+
+/**
+ * This class implements the DOM Level 3 Core interface DOMImplementationList.
+ *
+ * @xerces.internal
+ *
+ * @author Neil Delima, IBM
+ * @since DOM Level 3 Core
+ */
+public class DOMImplementationListImpl implements DOMImplementationList {
+
+ // A collection of DOMImplementations
+ private final ArrayList fImplementations;
+
+ /**
+ * Construct an empty list of DOMImplementations
+ */
+ public DOMImplementationListImpl() {
+ fImplementations = new ArrayList();
+ }
+
+ /**
+ * Construct a list of DOMImplementations from an ArrayList
+ */
+ public DOMImplementationListImpl(ArrayList params) {
+ fImplementations = params;
+ }
+
+ /**
+ * Construct a list of DOMImplementations from a Vector
+ */
+ public DOMImplementationListImpl(Vector params) {
+ fImplementations = new ArrayList(params);
+ }
+
+ /**
+ * Returns the indexth item in the collection.
+ *
+ * @param index The index of the DOMImplemetation from the list to return.
+ */
+ public DOMImplementation item(int index) {
+ final int length = getLength();
+ if (index >= 0 && index < length) {
+ return (DOMImplementation) fImplementations.get(index);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the number of DOMImplementations in the list.
+ *
+ * @return An integer indicating the number of DOMImplementations.
+ */
+ public int getLength() {
+ return fImplementations.size();
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DOMImplementationSourceImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DOMImplementationSourceImpl.java
new file mode 100644
index 0000000..883f73f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DOMImplementationSourceImpl.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.DOMImplementationList;
+import org.w3c.dom.DOMImplementationSource;
+
+/**
+ * Supply one the right implementation, based upon requested features. Each
+ * implemented DOMImplementationSource object is listed in the
+ * binding-specific list of available sources so that its
+ * DOMImplementation objects are made available.
+ *
+ * See also the Document Object Model (DOM) Level 3 Core Specification.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class DOMImplementationSourceImpl
+ implements DOMImplementationSource {
+
+ /**
+ * A method to request a DOM implementation.
+ * @param features A string that specifies which features are required.
+ * This is a space separated list in which each feature is specified
+ * by its name optionally followed by a space and a version number.
+ * This is something like: "XML 1.0 Traversal Events 2.0"
+ * @return An implementation that has the desired features, or
+ * null if this source has none.
+ */
+ public DOMImplementation getDOMImplementation(String features) {
+ // first check whether the CoreDOMImplementation would do
+ DOMImplementation impl =
+ CoreDOMImplementationImpl.getDOMImplementation();
+ if (testImpl(impl, features)) {
+ return impl;
+ }
+ // if not try the DOMImplementation
+ impl = DOMImplementationImpl.getDOMImplementation();
+ if (testImpl(impl, features)) {
+ return impl;
+ }
+
+ return null;
+ }
+
+ /**
+ * A method to request a list of DOM implementations that support the
+ * specified features and versions, as specified in .
+ * @param features A string that specifies which features and versions
+ * are required. This is a space separated list in which each feature
+ * is specified by its name optionally followed by a space and a
+ * version number. This is something like: "XML 3.0 Traversal +Events
+ * 2.0"
+ * @return A list of DOM implementations that support the desired
+ * features.
+ */
+ public DOMImplementationList getDOMImplementationList(String features) {
+ // first check whether the CoreDOMImplementation would do
+ DOMImplementation impl = CoreDOMImplementationImpl.getDOMImplementation();
+ final ArrayList implementations = new ArrayList();
+ if (testImpl(impl, features)) {
+ implementations.add(impl);
+ }
+ impl = DOMImplementationImpl.getDOMImplementation();
+ if (testImpl(impl, features)) {
+ implementations.add(impl);
+ }
+
+ return new DOMImplementationListImpl(implementations);
+ }
+
+ boolean testImpl(DOMImplementation impl, String features) {
+
+ StringTokenizer st = new StringTokenizer(features);
+ String feature = null;
+ String version = null;
+
+ if (st.hasMoreTokens()) {
+ feature = st.nextToken();
+ }
+ while (feature != null) {
+ boolean isVersion = false;
+ if (st.hasMoreTokens()) {
+ char c;
+ version = st.nextToken();
+ c = version.charAt(0);
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ isVersion = true;
+ }
+ } else {
+ version = null;
+ }
+ if (isVersion) {
+ if (!impl.hasFeature(feature, version)) {
+ return false;
+ }
+ if (st.hasMoreTokens()) {
+ feature = st.nextToken();
+ } else {
+ feature = null;
+ }
+ } else {
+ if (!impl.hasFeature(feature, null)) {
+ return false;
+ }
+ feature = version;
+ }
+ }
+ return true;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DOMInputImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DOMInputImpl.java
new file mode 100644
index 0000000..5023702
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DOMInputImpl.java
@@ -0,0 +1,389 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.w3c.dom.ls.LSInput;
+
+/**
+ * This Class DOMInputImpl represents a single input source for an XML entity.
+ * This Class allows an application to encapsulate information about
+ * an input source in a single object, which may include a public
+ * identifier, a system identifier, a byte stream (possibly with a specified
+ * encoding), and/or a character stream.
+ * The exact definitions of a byte stream and a character stream are
+ * binding dependent.
+ * There are two places that the application will deliver this input
+ * source to the parser: as the argument to the parse method,
+ * or as the return value of the DOMResourceResolver.resolveEntity
+ * method.
+ * The DOMParser will use the LSInput
+ * object to determine how to read XML input. If there is a character stream
+ * available, the parser will read that stream directly; if not, the parser
+ * will use a byte stream, if available; if neither a character stream nor a
+ * byte stream is available, the parser will attempt to open a URI
+ * connection to the resource identified by the system identifier.
+ * An LSInput object belongs to the application: the
+ * parser shall never modify it in any way (it may modify a copy if
+ * necessary). Eventhough all attributes in this interface are writable the
+ * DOM implementation is expected to never mutate a LSInput.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ *
+ * @xerces.internal
+ *
+ * @author Gopal Sharma, SUN Microsystems Inc.
+ * @version $Id$
+ */
+
+// REVISIT:
+// 1. it should be possible to do the following
+// DOMInputImpl extends XMLInputSource implements LSInput
+// 2. we probably need only the default constructor. -- el
+
+public class DOMInputImpl implements LSInput {
+
+ //
+ // Data
+ //
+
+ protected String fPublicId = null;
+ protected String fSystemId = null;
+ protected String fBaseSystemId = null;
+
+ protected InputStream fByteStream = null;
+ protected Reader fCharStream = null;
+ protected String fData = null;
+
+ protected String fEncoding = null;
+
+ protected boolean fCertifiedText = false;
+
+ /**
+ * Default Constructor, constructs an input source
+ *
+ *
+ */
+ public DOMInputImpl() {}
+
+ /**
+ * Constructs an input source from just the public and system
+ * identifiers, leaving resolution of the entity and opening of
+ * the input stream up to the caller.
+ *
+ * @param publicId The public identifier, if known.
+ * @param systemId The system identifier. This value should
+ * always be set, if possible, and can be
+ * relative or absolute. If the system identifier
+ * is relative, then the base system identifier
+ * should be set.
+ * @param baseSystemId The base system identifier. This value should
+ * always be set to the fully expanded URI of the
+ * base system identifier, if possible.
+ */
+
+ public DOMInputImpl(String publicId, String systemId,
+ String baseSystemId) {
+
+ fPublicId = publicId;
+ fSystemId = systemId;
+ fBaseSystemId = baseSystemId;
+
+ } // DOMInputImpl(String,String,String)
+
+ /**
+ * Constructs an input source from a byte stream.
+ *
+ * @param publicId The public identifier, if known.
+ * @param systemId The system identifier. This value should
+ * always be set, if possible, and can be
+ * relative or absolute. If the system identifier
+ * is relative, then the base system identifier
+ * should be set.
+ * @param baseSystemId The base system identifier. This value should
+ * always be set to the fully expanded URI of the
+ * base system identifier, if possible.
+ * @param byteStream The byte stream.
+ * @param encoding The encoding of the byte stream, if known.
+ */
+
+ public DOMInputImpl(String publicId, String systemId,
+ String baseSystemId, InputStream byteStream,
+ String encoding) {
+
+ fPublicId = publicId;
+ fSystemId = systemId;
+ fBaseSystemId = baseSystemId;
+ fByteStream = byteStream;
+ fEncoding = encoding;
+
+ } // DOMInputImpl(String,String,String,InputStream,String)
+
+ /**
+ * Constructs an input source from a character stream.
+ *
+ * @param publicId The public identifier, if known.
+ * @param systemId The system identifier. This value should
+ * always be set, if possible, and can be
+ * relative or absolute. If the system identifier
+ * is relative, then the base system identifier
+ * should be set.
+ * @param baseSystemId The base system identifier. This value should
+ * always be set to the fully expanded URI of the
+ * base system identifier, if possible.
+ * @param charStream The character stream.
+ * @param encoding The original encoding of the byte stream
+ * used by the reader, if known.
+ */
+
+ public DOMInputImpl(String publicId, String systemId,
+ String baseSystemId, Reader charStream,
+ String encoding) {
+
+ fPublicId = publicId;
+ fSystemId = systemId;
+ fBaseSystemId = baseSystemId;
+ fCharStream = charStream;
+ fEncoding = encoding;
+
+ } // DOMInputImpl(String,String,String,Reader,String)
+
+ /**
+ * Constructs an input source from a String.
+ *
+ * @param publicId The public identifier, if known.
+ * @param systemId The system identifier. This value should
+ * always be set, if possible, and can be
+ * relative or absolute. If the system identifier
+ * is relative, then the base system identifier
+ * should be set.
+ * @param baseSystemId The base system identifier. This value should
+ * always be set to the fully expanded URI of the
+ * base system identifier, if possible.
+ * @param data The String Data.
+ * @param encoding The original encoding of the byte stream
+ * used by the reader, if known.
+ */
+
+ public DOMInputImpl(String publicId, String systemId,
+ String baseSystemId, String data,
+ String encoding) {
+ fPublicId = publicId;
+ fSystemId = systemId;
+ fBaseSystemId = baseSystemId;
+ fData = data;
+ fEncoding = encoding;
+ } // DOMInputImpl(String,String,String,String,String)
+
+ /**
+ * An attribute of a language-binding dependent type that represents a
+ * stream of bytes.
+ * The parser will ignore this if there is also a character stream
+ * specified, but it will use a byte stream in preference to opening a
+ * URI connection itself.
+ * If the application knows the character encoding of the byte stream,
+ * it should set the encoding property. Setting the encoding in this way
+ * will override any encoding specified in the XML declaration itself.
+ */
+
+ public InputStream getByteStream(){
+ return fByteStream;
+ }
+
+ /**
+ * An attribute of a language-binding dependent type that represents a
+ * stream of bytes.
+ * The parser will ignore this if there is also a character stream
+ * specified, but it will use a byte stream in preference to opening a
+ * URI connection itself.
+ * If the application knows the character encoding of the byte stream,
+ * it should set the encoding property. Setting the encoding in this way
+ * will override any encoding specified in the XML declaration itself.
+ */
+
+ public void setByteStream(InputStream byteStream){
+ fByteStream = byteStream;
+ }
+
+ /**
+ * An attribute of a language-binding dependent type that represents a
+ * stream of 16-bit units. Application must encode the stream using
+ * UTF-16 (defined in and Amendment 1 of ).
+ * If a character stream is specified, the parser will ignore any byte
+ * stream and will not attempt to open a URI connection to the system
+ * identifier.
+ */
+ public Reader getCharacterStream(){
+ return fCharStream;
+ }
+ /**
+ * An attribute of a language-binding dependent type that represents a
+ * stream of 16-bit units. Application must encode the stream using
+ * UTF-16 (defined in and Amendment 1 of ).
+ * If a character stream is specified, the parser will ignore any byte
+ * stream and will not attempt to open a URI connection to the system
+ * identifier.
+ */
+
+ public void setCharacterStream(Reader characterStream){
+ fCharStream = characterStream;
+ }
+
+ /**
+ * A string attribute that represents a sequence of 16 bit units (utf-16
+ * encoded characters).
+ * If string data is available in the input source, the parser will
+ * ignore the character stream and the byte stream and will not attempt
+ * to open a URI connection to the system identifier.
+ */
+ public String getStringData(){
+ return fData;
+ }
+
+ /**
+ * A string attribute that represents a sequence of 16 bit units (utf-16
+ * encoded characters).
+ * If string data is available in the input source, the parser will
+ * ignore the character stream and the byte stream and will not attempt
+ * to open a URI connection to the system identifier.
+ */
+
+ public void setStringData(String stringData){
+ fData = stringData;
+ }
+
+ /**
+ * The character encoding, if known. The encoding must be a string
+ * acceptable for an XML encoding declaration ( section 4.3.3 "Character
+ * Encoding in Entities").
+ * This attribute has no effect when the application provides a
+ * character stream. For other sources of input, an encoding specified
+ * by means of this attribute will override any encoding specified in
+ * the XML claration or the Text Declaration, or an encoding obtained
+ * from a higher level protocol, such as HTTP .
+ */
+
+ public String getEncoding(){
+ return fEncoding;
+ }
+
+ /**
+ * The character encoding, if known. The encoding must be a string
+ * acceptable for an XML encoding declaration ( section 4.3.3 "Character
+ * Encoding in Entities").
+ * This attribute has no effect when the application provides a
+ * character stream. For other sources of input, an encoding specified
+ * by means of this attribute will override any encoding specified in
+ * the XML claration or the Text Declaration, or an encoding obtained
+ * from a higher level protocol, such as HTTP .
+ */
+ public void setEncoding(String encoding){
+ fEncoding = encoding;
+ }
+
+ /**
+ * The public identifier for this input source. The public identifier is
+ * always optional: if the application writer includes one, it will be
+ * provided as part of the location information.
+ */
+ public String getPublicId(){
+ return fPublicId;
+ }
+ /**
+ * The public identifier for this input source. The public identifier is
+ * always optional: if the application writer includes one, it will be
+ * provided as part of the location information.
+ */
+ public void setPublicId(String publicId){
+ fPublicId = publicId;
+ }
+
+ /**
+ * The system identifier, a URI reference , for this input source. The
+ * system identifier is optional if there is a byte stream or a
+ * character stream, but it is still useful to provide one, since the
+ * application can use it to resolve relative URIs and can include it in
+ * error messages and warnings (the parser will attempt to fetch the
+ * ressource identifier by the URI reference only if there is no byte
+ * stream or character stream specified).
+ * If the application knows the character encoding of the object
+ * pointed to by the system identifier, it can register the encoding by
+ * setting the encoding attribute.
+ * If the system ID is a relative URI reference (see section 5 in ),
+ * the behavior is implementation dependent.
+ */
+ public String getSystemId(){
+ return fSystemId;
+ }
+ /**
+ * The system identifier, a URI reference , for this input source. The
+ * system identifier is optional if there is a byte stream or a
+ * character stream, but it is still useful to provide one, since the
+ * application can use it to resolve relative URIs and can include it in
+ * error messages and warnings (the parser will attempt to fetch the
+ * ressource identifier by the URI reference only if there is no byte
+ * stream or character stream specified).
+ * If the application knows the character encoding of the object
+ * pointed to by the system identifier, it can register the encoding by
+ * setting the encoding attribute.
+ * If the system ID is a relative URI reference (see section 5 in ),
+ * the behavior is implementation dependent.
+ */
+ public void setSystemId(String systemId){
+ fSystemId = systemId;
+ }
+
+ /**
+ * The base URI to be used (see section 5.1.4 in ) for resolving relative
+ * URIs to absolute URIs. If the baseURI is itself a relative URI, the
+ * behavior is implementation dependent.
+ */
+ public String getBaseURI(){
+ return fBaseSystemId;
+ }
+ /**
+ * The base URI to be used (see section 5.1.4 in ) for resolving relative
+ * URIs to absolute URIs. If the baseURI is itself a relative URI, the
+ * behavior is implementation dependent.
+ */
+ public void setBaseURI(String baseURI){
+ fBaseSystemId = baseURI;
+ }
+
+ /**
+ * If set to true, assume that the input is certified (see section 2.13
+ * in [XML 1.1]) when
+ * parsing [XML 1.1].
+ */
+ public boolean getCertifiedText(){
+ return fCertifiedText;
+ }
+
+ /**
+ * If set to true, assume that the input is certified (see section 2.13
+ * in [XML 1.1]) when
+ * parsing [XML 1.1].
+ */
+
+ public void setCertifiedText(boolean certifiedText){
+ fCertifiedText = certifiedText;
+ }
+
+}// class DOMInputImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DOMLocatorImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DOMLocatorImpl.java
new file mode 100644
index 0000000..2def831
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DOMLocatorImpl.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.DOMLocator;
+import org.w3c.dom.Node;
+
+
+/**
+ * DOMLocatorImpl is an implementaion that describes a location (e.g.
+ * where an error occured).
+ * See also the Document Object Model (DOM) Level 3 Core Specification.
+ *
+ * @xerces.internal
+ *
+ * @author Gopal Sharma, SUN Microsystems Inc.
+ * @version $Id$
+ */
+
+public class DOMLocatorImpl implements DOMLocator {
+
+ //
+ // Data
+ //
+
+ /**
+ * The column number where the error occured,
+ * or -1 if there is no column number available.
+ */
+ public int fColumnNumber = -1;
+
+ /**
+ * The line number where the error occured,
+ * or -1 if there is no line number available.
+ */
+ public int fLineNumber = -1;
+
+ /** related data node*/
+ public Node fRelatedNode = null;
+
+ /**
+ * The URI where the error occured,
+ * or null if there is no URI available.
+ */
+ public String fUri = null;
+
+ /**
+ * The byte offset into the input source this locator is pointing to or -1
+ * if there is no byte offset available
+ */
+ public int fByteOffset = -1;
+
+ /**
+ * The UTF-16, as defined in [Unicode] and Amendment 1 of [ISO/IEC 10646],
+ * offset into the input source this locator is pointing to or -1 if there
+ * is no UTF-16 offset available.
+ */
+ public int fUtf16Offset = -1;
+
+ //
+ // Constructors
+ //
+
+ public DOMLocatorImpl(){
+ }
+
+ public DOMLocatorImpl (int lineNumber, int columnNumber, String uri ){
+ fLineNumber = lineNumber ;
+ fColumnNumber = columnNumber ;
+ fUri = uri;
+ } // DOMLocatorImpl (int lineNumber, int columnNumber, String uri )
+
+ public DOMLocatorImpl (int lineNumber, int columnNumber, int utf16Offset, String uri ){
+ fLineNumber = lineNumber ;
+ fColumnNumber = columnNumber ;
+ fUri = uri;
+ fUtf16Offset = utf16Offset;
+ } // DOMLocatorImpl (int lineNumber, int columnNumber, int utf16Offset, String uri )
+
+ public DOMLocatorImpl (int lineNumber, int columnNumber, int byteoffset, Node relatedData, String uri ){
+ fLineNumber = lineNumber ;
+ fColumnNumber = columnNumber ;
+ fByteOffset = byteoffset ;
+ fRelatedNode = relatedData ;
+ fUri = uri;
+ } // DOMLocatorImpl (int lineNumber, int columnNumber, int offset, Node errorNode, String uri )
+
+ public DOMLocatorImpl (int lineNumber, int columnNumber, int byteoffset, Node relatedData, String uri, int utf16Offset ){
+ fLineNumber = lineNumber ;
+ fColumnNumber = columnNumber ;
+ fByteOffset = byteoffset ;
+ fRelatedNode = relatedData ;
+ fUri = uri;
+ fUtf16Offset = utf16Offset;
+ } // DOMLocatorImpl (int lineNumber, int columnNumber, int offset, Node errorNode, String uri )
+
+
+ /**
+ * The line number where the error occured, or -1 if there is no line
+ * number available.
+ */
+ public int getLineNumber(){
+ return fLineNumber;
+ }
+
+ /**
+ * The column number where the error occured, or -1 if there is no column
+ * number available.
+ */
+ public int getColumnNumber(){
+ return fColumnNumber;
+ }
+
+
+ /**
+ * The URI where the error occured, or null if there is no URI available.
+ */
+ public String getUri(){
+ return fUri;
+ }
+
+
+ public Node getRelatedNode(){
+ return fRelatedNode;
+ }
+
+
+ /**
+ * The byte offset into the input source this locator is pointing to or -1
+ * if there is no byte offset available
+ */
+ public int getByteOffset(){
+ return fByteOffset;
+ }
+
+ /**
+ * The UTF-16, as defined in [Unicode] and Amendment 1 of [ISO/IEC 10646],
+ * offset into the input source this locator is pointing to or -1 if there
+ * is no UTF-16 offset available.
+ */
+ public int getUtf16Offset(){
+ return fUtf16Offset;
+ }
+
+}// class DOMLocatorImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DOMMessageFormatter.java b/resources/xerces2-j-src/org/apache/xerces/dom/DOMMessageFormatter.java
new file mode 100644
index 0000000..36ce3f1
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DOMMessageFormatter.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Used to format DOM error messages, using the system locale.
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ * @version $Id$
+ */
+public class DOMMessageFormatter {
+
+ public static final String DOM_DOMAIN = "http://www.w3.org/dom/DOMTR";
+ public static final String XML_DOMAIN = "http://www.w3.org/TR/1998/REC-xml-19980210";
+ public static final String SERIALIZER_DOMAIN = "http://apache.org/xml/serializer";
+
+ private static ResourceBundle domResourceBundle = null;
+ private static ResourceBundle xmlResourceBundle = null;
+ private static ResourceBundle serResourceBundle = null;
+ private static Locale locale = null;
+
+ DOMMessageFormatter() {
+ locale = Locale.getDefault();
+ }
+
+ /**
+ * Formats a message with the specified arguments using the given
+ * locale information.
+ *
+ * @param domain domain from which error string is to come.
+ * @param key The message key.
+ * @param arguments The message replacement text arguments. The order
+ * of the arguments must match that of the placeholders
+ * in the actual message.
+ *
+ * @return the formatted message.
+ *
+ * @throws MissingResourceException Thrown if the message with the
+ * specified key cannot be found.
+ */
+ public static String formatMessage(String domain,
+ String key, Object[] arguments)
+ throws MissingResourceException {
+ ResourceBundle resourceBundle = getResourceBundle(domain);
+ if(resourceBundle == null){
+ init();
+ resourceBundle = getResourceBundle(domain);
+ if(resourceBundle == null)
+ throw new MissingResourceException("Unknown domain" + domain, null, key);
+ }
+ // format message
+ String msg;
+ try {
+ msg = key + ": " + resourceBundle.getString(key);
+ if (arguments != null) {
+ try {
+ msg = java.text.MessageFormat.format(msg, arguments);
+ }
+ catch (Exception e) {
+ msg = resourceBundle.getString("FormatFailed");
+ msg += " " + resourceBundle.getString(key);
+ }
+ }
+ } // error
+ catch (MissingResourceException e) {
+ msg = resourceBundle.getString("BadMessageKey");
+ throw new MissingResourceException(key, msg, key);
+ }
+
+ // no message
+ if (msg == null) {
+ msg = key;
+ if (arguments.length > 0) {
+ StringBuffer str = new StringBuffer(msg);
+ str.append('?');
+ for (int i = 0; i < arguments.length; i++) {
+ if (i > 0) {
+ str.append('&');
+ }
+ str.append(String.valueOf(arguments[i]));
+ }
+ }
+ }
+
+ return msg;
+ }
+
+ static ResourceBundle getResourceBundle(String domain) {
+ if (domain == DOM_DOMAIN || domain.equals(DOM_DOMAIN)) {
+ return domResourceBundle;
+ }
+ else if (domain == XML_DOMAIN || domain.equals(XML_DOMAIN)) {
+ return xmlResourceBundle;
+ }
+ else if (domain == SERIALIZER_DOMAIN || domain.equals(SERIALIZER_DOMAIN)) {
+ return serResourceBundle;
+ }
+ return null;
+ }
+
+ /**
+ * Initialize Message Formatter.
+ */
+ public static void init() {
+ Locale _locale = locale;
+ if (_locale == null) {
+ _locale = Locale.getDefault();
+ }
+ domResourceBundle = ResourceBundle.getBundle("org.apache.xerces.impl.msg.DOMMessages", _locale);
+ serResourceBundle = ResourceBundle.getBundle("org.apache.xerces.impl.msg.XMLSerializerMessages", _locale);
+ xmlResourceBundle = ResourceBundle.getBundle("org.apache.xerces.impl.msg.XMLMessages", _locale);
+ }
+
+ /**
+ * Set Locale to be used by the formatter.
+ * @param dlocale
+ */
+ public static void setLocale(Locale dlocale) {
+ locale = dlocale;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DOMNormalizer.java b/resources/xerces2-j-src/org/apache/xerces/dom/DOMNormalizer.java
new file mode 100644
index 0000000..2263f5f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DOMNormalizer.java
@@ -0,0 +1,2101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Vector;
+
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.impl.RevalidationHandler;
+import org.apache.xerces.impl.dtd.XMLDTDLoader;
+import org.apache.xerces.impl.dtd.XMLDTDValidator;
+import org.apache.xerces.impl.dv.XSSimpleType;
+import org.apache.xerces.impl.xs.util.SimpleLocator;
+import org.apache.xerces.util.AugmentationsImpl;
+import org.apache.xerces.util.NamespaceSupport;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XML11Char;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLAttributes;
+import org.apache.xerces.xni.XMLDocumentHandler;
+import org.apache.xerces.xni.XMLLocator;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.grammars.XMLGrammarDescription;
+import org.apache.xerces.xni.parser.XMLComponent;
+import org.apache.xerces.xni.parser.XMLDocumentSource;
+import org.apache.xerces.xs.AttributePSVI;
+import org.apache.xerces.xs.ElementPSVI;
+import org.apache.xerces.xs.XSTypeDefinition;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DOMError;
+import org.w3c.dom.DOMErrorHandler;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Entity;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+/**
+ * This class adds implementation for normalizeDocument method.
+ * It acts as if the document was going through a save and load cycle, putting
+ * the document in a "normal" form. The actual result depends on the features being set
+ * and governing what operations actually take place. See setNormalizationFeature for details.
+ * Noticeably this method normalizes Text nodes, makes the document "namespace wellformed",
+ * according to the algorithm described below in pseudo code, by adding missing namespace
+ * declaration attributes and adding or changing namespace prefixes, updates the replacement
+ * tree of EntityReference nodes, normalizes attribute values, etc.
+ * Mutation events, when supported, are generated to reflect the changes occuring on the
+ * document.
+ * See Namespace normalization for details on how namespace declaration attributes and prefixes
+ * are normalized.
+ *
+ * NOTE: There is an initial support for DOM revalidation with XML Schema as a grammar.
+ * The tree might not be validated correctly if entityReferences, CDATA sections are
+ * present in the tree. The PSVI information is not exposed, normalized data (including element
+ * default content is not available).
+ *
+ * @xerces.experimental
+ *
+ * @author Elena Litani, IBM
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @version $Id$
+ */
+public class DOMNormalizer implements XMLDocumentHandler {
+
+ //
+ // constants
+ //
+ /** Debug normalize document*/
+ protected final static boolean DEBUG_ND = false;
+ /** Debug namespace fix up algorithm*/
+ protected final static boolean DEBUG = false;
+ /** Debug document handler events */
+ protected final static boolean DEBUG_EVENTS = false;
+
+ /** prefix added by namespace fixup algorithm should follow a pattern "NS" + index*/
+ protected final static String PREFIX = "NS";
+
+ //
+ // Data
+ //
+ protected DOMConfigurationImpl fConfiguration = null;
+ protected CoreDocumentImpl fDocument = null;
+ protected final XMLAttributesProxy fAttrProxy = new XMLAttributesProxy();
+ protected final QName fQName = new QName();
+
+ /** Validation handler represents validator instance. */
+ protected RevalidationHandler fValidationHandler;
+
+ /** symbol table */
+ protected SymbolTable fSymbolTable;
+ /** error handler. may be null. */
+ protected DOMErrorHandler fErrorHandler;
+
+ /**
+ * Cached {@link DOMError} impl.
+ * The same object is re-used to report multiple errors.
+ */
+ private final DOMErrorImpl fError = new DOMErrorImpl();
+
+ // Validation against namespace aware grammar
+ protected boolean fNamespaceValidation = false;
+
+ // Update PSVI information in the tree
+ protected boolean fPSVI = false;
+
+ /** The namespace context of this document: stores namespaces in scope */
+ protected final NamespaceContext fNamespaceContext = new NamespaceSupport();
+
+ /** Stores all namespace bindings on the current element */
+ protected final NamespaceContext fLocalNSBinder = new NamespaceSupport();
+
+ /** list of attributes */
+ protected final ArrayList fAttributeList = new ArrayList(5);
+
+ /** DOM Locator - for namespace fixup algorithm */
+ protected final DOMLocatorImpl fLocator = new DOMLocatorImpl();
+
+ /** for setting the PSVI */
+ protected Node fCurrentNode = null;
+ private final QName fAttrQName = new QName();
+
+ // attribute value normalization
+ final XMLString fNormalizedValue = new XMLString(new char[16], 0, 0);
+
+ /**
+ * If the user stops the process, this exception will be thrown.
+ */
+ public static final RuntimeException abort = new RuntimeException() {
+ private static final long serialVersionUID = 5361322877988412432L;
+ public Throwable fillInStackTrace() {
+ return this;
+ }
+ };
+
+ /** Empty string to pass to the validator. **/
+ public static final XMLString EMPTY_STRING = new XMLString();
+
+ // Check if element content is all "ignorable whitespace"
+ private boolean fAllWhitespace = false;
+
+ // Constructor
+ //
+
+ public DOMNormalizer(){}
+
+
+
+ /**
+ * Normalizes document.
+ * Note: reset() must be called before this method.
+ */
+ protected void normalizeDocument(CoreDocumentImpl document, DOMConfigurationImpl config) {
+
+ fDocument = document;
+ fConfiguration = config;
+ fAllWhitespace = false;
+ fNamespaceValidation = false;
+
+ String xmlVersion = fDocument.getXmlVersion();
+ String schemaType = null;
+ String [] schemaLocations = null;
+
+ // intialize and reset DOMNormalizer component
+ //
+ fSymbolTable = (SymbolTable) fConfiguration.getProperty(DOMConfigurationImpl.SYMBOL_TABLE);
+ // reset namespace context
+ fNamespaceContext.reset();
+ fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, null);
+
+ if ((fConfiguration.features & DOMConfigurationImpl.VALIDATE) != 0) {
+ String schemaLang = (String)fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_LANGUAGE);
+
+ if (schemaLang != null && schemaLang.equals(Constants.NS_XMLSCHEMA)) {
+ schemaType = XMLGrammarDescription.XML_SCHEMA;
+ fValidationHandler = CoreDOMImplementationImpl.singleton.getValidator(schemaType, xmlVersion);
+ fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA, true);
+ fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA_FULL_CHECKING, true);
+ // report fatal error on DOM Level 1 nodes
+ fNamespaceValidation = true;
+
+ // check if we need to fill in PSVI
+ fPSVI = ((fConfiguration.features & DOMConfigurationImpl.PSVI) !=0)?true:false;
+ }
+ else {
+ schemaType = XMLGrammarDescription.XML_DTD;
+ if (schemaLang != null) {
+ schemaLocations = (String []) fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_SOURCE);
+ }
+ fConfiguration.setDTDValidatorFactory(xmlVersion);
+ fValidationHandler = CoreDOMImplementationImpl.singleton.getValidator(schemaType, xmlVersion);
+ fPSVI = false;
+ }
+
+ fConfiguration.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true);
+
+ // reset ID table
+ fDocument.clearIdentifiers();
+
+ if (fValidationHandler != null) {
+ // reset the validation handler
+ ((XMLComponent) fValidationHandler).reset(fConfiguration);
+ }
+ }
+ else {
+ fValidationHandler = null;
+ }
+
+ fErrorHandler = (DOMErrorHandler) fConfiguration.getParameter(Constants.DOM_ERROR_HANDLER);
+ if (fValidationHandler != null) {
+ fValidationHandler.setDocumentHandler(this);
+ fValidationHandler.startDocument(
+ new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI,
+ -1, -1 ), fDocument.encoding, fNamespaceContext, null);
+ fValidationHandler.xmlDecl(fDocument.getXmlVersion(),
+ fDocument.getXmlEncoding(), fDocument.getXmlStandalone() ? "yes" : "no", null);
+ }
+ try {
+ if (schemaType == XMLGrammarDescription.XML_DTD) {
+ processDTD(xmlVersion, schemaLocations != null ? schemaLocations[0] : null);
+ }
+
+ Node kid, next;
+ for (kid = fDocument.getFirstChild(); kid != null; kid = next) {
+ next = kid.getNextSibling();
+ kid = normalizeNode(kid);
+ if (kid != null) { // don't advance
+ next = kid;
+ }
+ }
+
+ // release resources
+ if (fValidationHandler != null) {
+ fValidationHandler.endDocument(null);
+ fValidationHandler.setDocumentHandler(null);
+ CoreDOMImplementationImpl.singleton.releaseValidator(schemaType, xmlVersion, fValidationHandler);
+ fValidationHandler = null;
+ }
+ }
+ catch (RuntimeException e) {
+ // release resources
+ if (fValidationHandler != null) {
+ fValidationHandler.setDocumentHandler(null);
+ CoreDOMImplementationImpl.singleton.releaseValidator(schemaType, xmlVersion, fValidationHandler);
+ fValidationHandler = null;
+ }
+ if (e == abort) {
+ return; // processing aborted by the user
+ }
+ throw e; // otherwise re-throw.
+ }
+ }
+
+ /**
+ *
+ * This method acts as if the document was going through a save
+ * and load cycle, putting the document in a "normal" form. The actual result
+ * depends on the features being set and governing what operations actually
+ * take place. See setNormalizationFeature for details. Noticeably this method
+ * normalizes Text nodes, makes the document "namespace wellformed",
+ * according to the algorithm described below in pseudo code, by adding missing
+ * namespace declaration attributes and adding or changing namespace prefixes, updates
+ * the replacement tree of EntityReference nodes,normalizes attribute values, etc.
+ *
+ * @param node Modified node or null. If node is returned, we need
+ * to normalize again starting on the node returned.
+ * @return the normalized Node
+ */
+ protected Node normalizeNode (Node node){
+
+ int type = node.getNodeType();
+ boolean wellformed;
+ fLocator.fRelatedNode=node;
+
+ switch (type) {
+ case Node.DOCUMENT_TYPE_NODE: {
+ if (DEBUG_ND) {
+ System.out.println("==>normalizeNode:{doctype}");
+ }
+ // REVISIT: well-formedness encoding info
+ break;
+ }
+
+ case Node.ELEMENT_NODE: {
+ if (DEBUG_ND) {
+ System.out.println("==>normalizeNode:{element} "+node.getNodeName());
+ }
+
+ //do the name check only when version of the document was changed &
+ //application has set the value of well-formed features to true
+ if (fDocument.errorChecking) {
+ if ( ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) &&
+ fDocument.isXMLVersionChanged()){
+ if (fNamespaceValidation){
+ wellformed = CoreDocumentImpl.isValidQName(node.getPrefix() , node.getLocalName(), fDocument.isXML11Version());
+ }
+ else {
+ wellformed = CoreDocumentImpl.isXMLName(node.getNodeName() , fDocument.isXML11Version());
+ }
+ if (!wellformed){
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "wf-invalid-character-in-node-name",
+ new Object[]{"Element", node.getNodeName()});
+ reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
+ "wf-invalid-character-in-node-name");
+ }
+ }
+ }
+ // push namespace context
+ fNamespaceContext.pushContext();
+ fLocalNSBinder.reset();
+
+ ElementImpl elem = (ElementImpl)node;
+ if (elem.needsSyncChildren()) {
+ elem.synchronizeChildren();
+ }
+ AttributeMap attributes = (elem.hasAttributes()) ? (AttributeMap) elem.getAttributes() : null;
+
+ // fix namespaces and remove default attributes
+ if ((fConfiguration.features & DOMConfigurationImpl.NAMESPACES) !=0) {
+ // fix namespaces
+ // normalize attribute values
+ // remove default attributes
+ namespaceFixUp(elem, attributes);
+
+ if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0) {
+ // Namespace declarations may have been added by namespace fix-up. Need
+ // to fetch the AttributeMap again if it contained no attributes prior
+ // to namespace fix-up.
+ if (attributes == null) {
+ attributes = (elem.hasAttributes()) ? (AttributeMap) elem.getAttributes() : null;
+ }
+ if (attributes != null) {
+ for (int i = 0; i < attributes.getLength(); ++i) {
+ Attr att = (Attr)attributes.getItem(i);
+ if (XMLSymbols.PREFIX_XMLNS.equals(att.getPrefix()) ||
+ XMLSymbols.PREFIX_XMLNS.equals(att.getName())) {
+ elem.removeAttributeNode(att);
+ --i;
+ }
+ }
+ }
+ }
+
+ } else {
+ if ( attributes!=null ) {
+ for ( int i=0; inormalizeNode:{comments}");
+ }
+
+ if ((fConfiguration.features & DOMConfigurationImpl.COMMENTS) == 0) {
+ Node prevSibling = node.getPreviousSibling();
+ Node parent = node.getParentNode();
+ // remove the comment node
+ parent.removeChild(node);
+ if (prevSibling != null && prevSibling.getNodeType() == Node.TEXT_NODE) {
+ Node nextSibling = prevSibling.getNextSibling();
+ if (nextSibling != null && nextSibling.getNodeType() == Node.TEXT_NODE) {
+ ((TextImpl)nextSibling).insertData(0, prevSibling.getNodeValue());
+ parent.removeChild(prevSibling);
+ return nextSibling;
+ }
+ }
+ }//if comment node need not be removed
+ else {
+ if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)){
+ String commentdata = ((Comment)node).getData();
+ // check comments for invalid xml chracter as per the version
+ // of the document
+ isCommentWF(fErrorHandler, fError, fLocator, commentdata, fDocument.isXML11Version());
+ }
+ if (fValidationHandler != null) {
+ // Don't bother filling an XMLString with the text of the comment.
+ // We only send the comment event to the validator handler so that
+ // when the schema-type is DTD an error will be reported for a
+ // comment appearing in EMPTY content.
+ fValidationHandler.comment(EMPTY_STRING, null);
+ }
+ }//end-else if comment node is not to be removed.
+ break;
+ }
+ case Node.ENTITY_REFERENCE_NODE: {
+ if (DEBUG_ND) {
+ System.out.println("==>normalizeNode:{entityRef} "+node.getNodeName());
+ }
+
+ if ((fConfiguration.features & DOMConfigurationImpl.ENTITIES) == 0) {
+ Node prevSibling = node.getPreviousSibling();
+ Node parent = node.getParentNode();
+ ((EntityReferenceImpl)node).setReadOnly(false, true);
+ expandEntityRef (parent, node);
+ parent.removeChild(node);
+ Node next = (prevSibling != null)?prevSibling.getNextSibling():parent.getFirstChild();
+ // The list of children #text -> &ent;
+ // and entity has a first child as a text
+ // we should not advance
+ if (prevSibling != null && next != null && prevSibling.getNodeType() == Node.TEXT_NODE &&
+ next.getNodeType() == Node.TEXT_NODE) {
+ return prevSibling; // Don't advance
+ }
+ return next;
+ } else {
+ if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) &&
+ fDocument.isXMLVersionChanged()){
+ CoreDocumentImpl.isXMLName(node.getNodeName() , fDocument.isXML11Version());
+ }
+ // REVISIT: traverse entity reference and send appropriate calls to the validator
+ // (no normalization should be performed for the children).
+ }
+ break;
+ }
+
+ case Node.CDATA_SECTION_NODE: {
+ if (DEBUG_ND) {
+ System.out.println("==>normalizeNode:{cdata}");
+ }
+
+ if ((fConfiguration.features & DOMConfigurationImpl.CDATA) == 0) {
+ // convert CDATA to TEXT nodes
+ Node prevSibling = node.getPreviousSibling();
+ if (prevSibling != null && prevSibling.getNodeType() == Node.TEXT_NODE){
+ ((Text)prevSibling).appendData(node.getNodeValue());
+ node.getParentNode().removeChild(node);
+ return prevSibling; //don't advance
+ }
+ else {
+ Text text = fDocument.createTextNode(node.getNodeValue());
+ Node parent = node.getParentNode();
+ node = parent.replaceChild(text, node);
+ return text; //don't advance
+
+ }
+ }
+
+ // send characters call for CDATA
+ if (fValidationHandler != null) {
+ // set error node in the dom error wrapper
+ // so if error occurs we can report an error node
+ fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
+ fCurrentNode = node;
+ fValidationHandler.startCDATA(null);
+ fValidationHandler.characterData(node.getNodeValue(), null);
+ fValidationHandler.endCDATA(null);
+ }
+ String value = node.getNodeValue();
+
+ if ((fConfiguration.features & DOMConfigurationImpl.SPLITCDATA) != 0) {
+ int index;
+ Node parent = node.getParentNode();
+ if (fDocument.errorChecking) {
+ isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), fDocument.isXML11Version());
+ }
+ while ( (index=value.indexOf("]]>")) >= 0 ) {
+ node.setNodeValue(value.substring(0, index+2));
+ value = value.substring(index +2);
+
+ Node firstSplitNode = node;
+ Node newChild = fDocument.createCDATASection(value);
+ parent.insertBefore(newChild, node.getNextSibling());
+ node = newChild;
+ // issue warning
+ fLocator.fRelatedNode = firstSplitNode;
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "cdata-sections-splitted",
+ null);
+ reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_WARNING,
+ "cdata-sections-splitted");
+ }
+
+ }
+ else if (fDocument.errorChecking) {
+ // check well-formedness
+ isCDataWF(fErrorHandler, fError, fLocator, value, fDocument.isXML11Version());
+ }
+ break;
+ }
+
+ case Node.TEXT_NODE: {
+ if (DEBUG_ND) {
+ System.out.println("==>normalizeNode(text):{"+node.getNodeValue()+"}");
+ }
+ // If node is a text node, we need to check for one of two
+ // conditions:
+ // 1) There is an adjacent text node
+ // 2) There is no adjacent text node, but node is
+ // an empty text node.
+ Node next = node.getNextSibling();
+ // If an adjacent text node, merge it with this node
+ if ( next!=null && next.getNodeType() == Node.TEXT_NODE ) {
+ ((Text)node).appendData(next.getNodeValue());
+ node.getParentNode().removeChild( next );
+ // We don't need to check well-formness here since we are not yet
+ // done with this node.
+
+ return node; // Don't advance;
+ } else if (node.getNodeValue().length()==0) {
+ // If kid is empty, remove it
+ node.getParentNode().removeChild( node );
+ } else {
+ // validator.characters() call and well-formness
+ // Don't send characters or check well-formness in the following cases:
+ // 1. entities is false, next child is entity reference: expand tree first
+ // 2. comments is false, and next child is comment
+ // 3. cdata is false, and next child is cdata
+
+ short nextType = (next != null)?next.getNodeType():-1;
+ if (nextType == -1 || !(((fConfiguration.features & DOMConfigurationImpl.ENTITIES) == 0 &&
+ nextType == Node.ENTITY_NODE) ||
+ ((fConfiguration.features & DOMConfigurationImpl.COMMENTS) == 0 &&
+ nextType == Node.COMMENT_NODE) ||
+ ((fConfiguration.features & DOMConfigurationImpl.CDATA) == 0) &&
+ nextType == Node.CDATA_SECTION_NODE)) {
+ if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) ){
+ isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), fDocument.isXML11Version());
+ }
+ if (fValidationHandler != null) {
+ fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
+ fCurrentNode = node;
+ fValidationHandler.characterData(node.getNodeValue(), null);
+ if (!fNamespaceValidation) {
+ if (fAllWhitespace) {
+ fAllWhitespace = false;
+ ((TextImpl)node).setIgnorableWhitespace(true);
+ }
+ else {
+ ((TextImpl)node).setIgnorableWhitespace(false);
+ }
+ }
+ if (DEBUG_ND) {
+ System.out.println("=====>characterData(),"+nextType);
+ }
+ }
+ }
+ else {
+ if (DEBUG_ND) {
+ System.out.println("=====>don't send characters(),"+nextType);
+
+ }
+ }
+ }
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE: {
+
+ //do the well-formed valid PI target name , data check when application has set the value of well-formed feature to true
+ if (fDocument.errorChecking && (fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0 ) {
+ ProcessingInstruction pinode = (ProcessingInstruction)node ;
+
+ String target = pinode.getTarget();
+ //1.check PI target name
+ if(fDocument.isXML11Version()){
+ wellformed = XML11Char.isXML11ValidName(target);
+ }
+ else{
+ wellformed = XMLChar.isValidName(target);
+ }
+
+ if (!wellformed) {
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "wf-invalid-character-in-node-name",
+ new Object[]{"Element", node.getNodeName()});
+ reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
+ "wf-invalid-character-in-node-name");
+ }
+
+ //2. check PI data
+ //processing isntruction data may have certain characters
+ //which may not be valid XML character
+ isXMLCharWF(fErrorHandler, fError, fLocator, pinode.getData(), fDocument.isXML11Version());
+ }
+
+ if (fValidationHandler != null) {
+ // Don't bother filling an XMLString with the data section of the
+ // processing instruction. We only send the processing instruction
+ // event to the validator handler so that when the schema-type is
+ // DTD an error will be reported for a processing instruction
+ // appearing in EMPTY content.
+ fValidationHandler.processingInstruction(((ProcessingInstruction) node).getTarget(), EMPTY_STRING, null);
+ }
+ }//end case Node.PROCESSING_INSTRUCTION_NODE
+
+ }//end of switch
+ return null;
+ }//normalizeNode
+
+ private void processDTD(String xmlVersion, String schemaLocation) {
+
+ String rootName = null;
+ String publicId = null;
+ String systemId = schemaLocation;
+ String baseSystemId = fDocument.getDocumentURI();
+ String internalSubset = null;
+
+ DocumentType docType = fDocument.getDoctype();
+ if (docType != null) {
+ rootName = docType.getName();
+ publicId = docType.getPublicId();
+ if (systemId == null || systemId.length() == 0) {
+ systemId = docType.getSystemId();
+ }
+ internalSubset = docType.getInternalSubset();
+ }
+ // If the DOM doesn't have a DocumentType node we may still
+ // be able to fetch a DTD if the application provided a URI
+ else {
+ Element elem = fDocument.getDocumentElement();
+ if (elem == null) return;
+ rootName = elem.getNodeName();
+ if (systemId == null || systemId.length() == 0) return;
+ }
+
+ XMLDTDLoader loader = null;
+ try {
+ fValidationHandler.doctypeDecl(rootName, publicId, systemId, null);
+ loader = CoreDOMImplementationImpl.singleton.getDTDLoader(xmlVersion);
+ loader.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true);
+ loader.setEntityResolver(fConfiguration.getEntityResolver());
+ loader.setErrorHandler(fConfiguration.getErrorHandler());
+ loader.loadGrammarWithContext((XMLDTDValidator) fValidationHandler, rootName,
+ publicId, systemId, baseSystemId, internalSubset);
+ }
+ // REVISIT: Should probably report this exception to the error handler.
+ catch (IOException e) {
+ }
+ finally {
+ if (loader != null) {
+ CoreDOMImplementationImpl.singleton.releaseDTDLoader(xmlVersion, loader);
+ }
+ }
+ } // processDTD(String, String)
+
+ protected final void expandEntityRef (Node parent, Node reference){
+ Node kid, next;
+ for (kid = reference.getFirstChild(); kid != null; kid = next) {
+ next = kid.getNextSibling();
+ parent.insertBefore(kid, reference);
+ }
+ }
+
+ // fix namespaces
+ // normalize attribute values
+ // remove default attributes
+ // check attribute names if the version of the document changed.
+
+ protected final void namespaceFixUp (ElementImpl element, AttributeMap attributes){
+ if (DEBUG) {
+ System.out.println("[ns-fixup] element:" +element.getNodeName()+
+ " uri: "+element.getNamespaceURI());
+ }
+
+ // ------------------------------------
+ // pick up local namespace declarations
+ //
+ //
+ //
+ //
+ // ------------------------------------
+
+ String value, uri, prefix;
+ if (attributes != null) {
+
+ // Record all valid local declarations
+ for (int k = 0; k < attributes.getLength(); ++k) {
+ Attr attr = (Attr)attributes.getItem(k);
+ uri = attr.getNamespaceURI();
+ if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) {
+ // namespace attribute
+ value = attr.getNodeValue();
+ if (value == null) {
+ value=XMLSymbols.EMPTY_STRING;
+ }
+
+ // Check for invalid namespace declaration:
+ if (fDocument.errorChecking && value.equals(NamespaceContext.XMLNS_URI)) {
+ //A null value for locale is passed to formatMessage,
+ //which means that the default locale will be used
+ fLocator.fRelatedNode = attr;
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,"CantBindXMLNS",null );
+ reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, "CantBindXMLNS");
+ } else {
+ // XML 1.0 Attribute value normalization
+ // value = normalizeAttributeValue(value, attr);
+ prefix = attr.getPrefix();
+ prefix = (prefix == null ||
+ prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix);
+ String localpart = fSymbolTable.addSymbol( attr.getLocalName());
+ if (prefix == XMLSymbols.PREFIX_XMLNS) { //xmlns:prefix
+
+ value = fSymbolTable.addSymbol(value);
+ if (value.length() != 0) {
+ fNamespaceContext.declarePrefix(localpart, value);
+ } else {
+ // REVISIT: issue error on invalid declarations
+ // xmlns:foo = ""
+
+ }
+ //removeDefault (attr, attributes);
+ continue;
+ } else { // (localpart == fXmlnsSymbol && prefix == fEmptySymbol) -- xmlns
+ // empty prefix is always bound ("" or some string)
+ value = fSymbolTable.addSymbol(value);
+ fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, value.length() != 0 ? value : null);
+ //removeDefault (attr, attributes);
+ continue;
+ }
+ } // end-else: valid declaration
+ } // end-if: namespace attribute
+ }
+ }
+
+
+
+ // ---------------------------------------------------------
+ // Fix up namespaces for element: per DOM L3
+ // Need to consider the following cases:
+ //
+ // case 1:
+ // We create another element body bound to the "http://xsl" namespace
+ // as well as namespace attribute rebounding xsl to another namespace.
+ //
+ // Need to make sure that the new namespace decl value is changed to
+ // "http://xsl"
+ //
+ // ---------------------------------------------------------
+ // check if prefix/namespace is correct for current element
+ // ---------------------------------------------------------
+
+ uri = element.getNamespaceURI();
+ prefix = element.getPrefix();
+ if (uri != null) { // Element has a namespace
+ uri = fSymbolTable.addSymbol(uri);
+ prefix = (prefix == null ||
+ prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix);
+ if (fNamespaceContext.getURI(prefix) == uri) {
+ // The xmlns:prefix=namespace or xmlns="default" was declared at parent.
+ // The binder always stores mapping of empty prefix to "".
+ } else {
+ // the prefix is either undeclared
+ // or
+ // conflict: the prefix is bound to another URI
+ addNamespaceDecl(prefix, uri, element);
+ fLocalNSBinder.declarePrefix(prefix, uri);
+ fNamespaceContext.declarePrefix(prefix, uri);
+ }
+ } else { // Element has no namespace
+ if (element.getLocalName() == null) {
+
+ // Error: DOM Level 1 node!
+ if (fNamespaceValidation) {
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN, "NullLocalElementName",
+ new Object[]{element.getNodeName()});
+ reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR,
+ "NullLocalElementName");
+ } else {
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN, "NullLocalElementName",
+ new Object[]{element.getNodeName()});
+ reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
+ "NullLocalElementName");
+ }
+
+ } else { // uri=null and no colon (DOM L2 node)
+ uri = fNamespaceContext.getURI(XMLSymbols.EMPTY_STRING);
+ if (uri !=null && uri.length() > 0) {
+ // undeclare default namespace declaration (before that element
+ // bound to non-zero length uir), but adding xmlns="" decl
+ addNamespaceDecl (XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING, element);
+ fLocalNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, null);
+ fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, null);
+ }
+ }
+ }
+
+ // -----------------------------------------
+ // Fix up namespaces for attributes: per DOM L3
+ // check if prefix/namespace is correct the attributes
+ // -----------------------------------------
+ if (attributes != null) {
+
+ // clone content of the attributes
+ attributes.cloneMap(fAttributeList);
+ for (int i = 0; i < fAttributeList.size(); i++) {
+ Attr attr = (Attr) fAttributeList.get(i);
+ fLocator.fRelatedNode = attr;
+
+ if (DEBUG) {
+ System.out.println("==>[ns-fixup] process attribute: "+attr.getNodeName());
+ }
+ // normalize attribute value
+ attr.normalize();
+ value = attr.getValue();
+ uri = attr.getNamespaceURI();
+
+ // make sure that value is never null.
+ if (value == null) {
+ value = XMLSymbols.EMPTY_STRING;
+ }
+
+ //---------------------------------------
+ // check if value of the attribute is namespace well-formed
+ //---------------------------------------
+ if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)) {
+ isAttrValueWF(fErrorHandler, fError, fLocator, attributes, attr, value, fDocument.isXML11Version());
+ if (fDocument.isXMLVersionChanged()) {
+ boolean wellformed;
+ if (fNamespaceValidation){
+ wellformed = CoreDocumentImpl.isValidQName(attr.getPrefix(), attr.getLocalName(), fDocument.isXML11Version());
+ }
+ else {
+ wellformed = CoreDocumentImpl.isXMLName(attr.getNodeName(), fDocument.isXML11Version());
+ }
+ if (!wellformed) {
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "wf-invalid-character-in-node-name",
+ new Object[]{"Attr", attr.getNodeName()});
+ reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
+ "wf-invalid-character-in-node-name");
+ }
+ }
+ }
+
+ if (uri != null) { // attribute has namespace !=null
+ prefix = attr.getPrefix();
+ prefix = (prefix == null ||
+ prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix);
+ /*String localpart =*/ fSymbolTable.addSymbol( attr.getLocalName());
+
+ // ---------------------------------------
+ // skip namespace declarations
+ // ---------------------------------------
+ // REVISIT: can we assume that "uri" is from some symbol
+ // table, and compare by reference? -SG
+ if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) {
+ continue;
+ }
+
+ // ---------------------------------------
+ // remove default attributes
+ // ---------------------------------------
+ /*
+ if (removeDefault(attr, attributes)) {
+ continue;
+ }
+ */
+ // XML 1.0 Attribute value normalization
+ //value = normalizeAttributeValue(value, attr);
+
+ // reset id-attributes
+ ((AttrImpl)attr).setIdAttribute(false);
+
+ uri = fSymbolTable.addSymbol(uri);
+
+ // find if for this prefix a URI was already declared
+ String declaredURI = fNamespaceContext.getURI(prefix);
+
+ if (prefix == XMLSymbols.EMPTY_STRING || declaredURI != uri) {
+ // attribute has no prefix (default namespace decl does not apply to attributes)
+ // OR
+ // attribute prefix is not declared
+ // OR
+ // conflict: attribute has a prefix that conficlicts with a binding
+ // already active in scope
+
+ // Find if any prefix for attributes namespace URI is available
+ // in the scope
+ String declaredPrefix = fNamespaceContext.getPrefix(uri);
+ if (declaredPrefix !=null && declaredPrefix !=XMLSymbols.EMPTY_STRING) {
+
+ // use the prefix that was found (declared previously for this URI
+ prefix = declaredPrefix;
+ } else {
+ if (prefix != XMLSymbols.EMPTY_STRING && fLocalNSBinder.getURI(prefix) == null) {
+ // the current prefix is not null and it has no in scope declaration
+
+ // use this prefix
+ } else {
+
+ // find a prefix following the pattern "NS" +index (starting at 1)
+ // make sure this prefix is not declared in the current scope.
+ int counter = 1;
+ prefix = fSymbolTable.addSymbol(PREFIX +counter++);
+ while (fLocalNSBinder.getURI(prefix)!=null) {
+ prefix = fSymbolTable.addSymbol(PREFIX +counter++);
+ }
+
+ }
+ // add declaration for the new prefix
+ addNamespaceDecl(prefix, uri, element);
+ value = fSymbolTable.addSymbol(value);
+ fLocalNSBinder.declarePrefix(prefix, value);
+ fNamespaceContext.declarePrefix(prefix, uri);
+ }
+
+ // change prefix for this attribute
+ attr.setPrefix(prefix);
+ }
+ } else { // attribute uri == null
+
+ // XML 1.0 Attribute value normalization
+ //value = normalizeAttributeValue(value, attr);
+
+ // reset id-attributes
+ ((AttrImpl)attr).setIdAttribute(false);
+
+ if (attr.getLocalName() == null) {
+ // It is an error if document has DOM L1 nodes.
+ if (fNamespaceValidation) {
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NullLocalAttrName", new Object[]{attr.getNodeName()});
+ reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR,
+ "NullLocalAttrName");
+ } else {
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NullLocalAttrName", new Object[]{attr.getNodeName()});
+ reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
+ "NullLocalAttrName");
+ }
+ } else {
+ // uri=null and no colon
+ // no fix up is needed: default namespace decl does not
+
+ // ---------------------------------------
+ // remove default attributes
+ // ---------------------------------------
+ // removeDefault(attr, attributes);
+ }
+ }
+ }
+ } // end loop for attributes
+ }
+
+ /**
+ * Adds a namespace attribute or replaces the value of existing namespace
+ * attribute with the given prefix and value for URI.
+ * In case prefix is empty will add/update default namespace declaration.
+ *
+ * @param prefix
+ * @param uri
+ * @exception IOException
+ */
+
+ protected final void addNamespaceDecl(String prefix, String uri, ElementImpl element){
+ if (DEBUG) {
+ System.out.println("[ns-fixup] addNamespaceDecl ["+prefix+"]");
+ }
+ if (prefix == XMLSymbols.EMPTY_STRING) {
+ if (DEBUG) {
+ System.out.println("=>add xmlns=\""+uri+"\" declaration");
+ }
+ element.setAttributeNS(NamespaceContext.XMLNS_URI, XMLSymbols.PREFIX_XMLNS, uri);
+ } else {
+ if (DEBUG) {
+ System.out.println("=>add xmlns:"+prefix+"=\""+uri+"\" declaration");
+ }
+ element.setAttributeNS(NamespaceContext.XMLNS_URI, "xmlns:"+prefix, uri);
+ }
+ }
+
+
+ //
+ // Methods for well-formness checking
+ //
+
+
+ /**
+ * Check if CDATA section is well-formed
+ * @param datavalue
+ * @param isXML11Version = true if XML 1.1
+ */
+ public static final void isCDataWF(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator,
+ String datavalue, boolean isXML11Version)
+ {
+ if (datavalue == null || (datavalue.length() == 0) ) {
+ return;
+ }
+
+ char [] dataarray = datavalue.toCharArray();
+ int datalength = dataarray.length;
+
+ // version of the document is XML 1.1
+ if (isXML11Version) {
+ // we need to check all chracters as per production rules of XML11
+ int i = 0;
+ while(i < datalength){
+ char c = dataarray[i++];
+ if ( XML11Char.isXML11Invalid(c) ) {
+ // check if this is a supplemental character
+ if (XMLChar.isHighSurrogate(c) && i < datalength) {
+ char c2 = dataarray[i++];
+ if (XMLChar.isLowSurrogate(c2) &&
+ XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) {
+ continue;
+ }
+ }
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.XML_DOMAIN,
+ "InvalidCharInCDSect",
+ new Object[] { Integer.toString(c, 16)});
+ reportDOMError(
+ errorHandler,
+ error,
+ locator,
+ msg,
+ DOMError.SEVERITY_ERROR,
+ "wf-invalid-character");
+ }
+ else if (c == ']') {
+ int count = i;
+ if (count < datalength && dataarray[count] == ']') {
+ while (++count < datalength && dataarray[count] == ']') {
+ // do nothing
+ }
+ if (count < datalength && dataarray[count] == '>') {
+ // CDEndInContent
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, "CDEndInContent", null);
+ reportDOMError(errorHandler, error, locator,msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
+ }
+ }
+
+ }
+ }
+ } // version of the document is XML 1.0
+ else {
+ // we need to check all chracters as per production rules of XML 1.0
+ int i = 0;
+ while (i < datalength) {
+ char c = dataarray[i++];
+ if( XMLChar.isInvalid(c) ) {
+ // check if this is a supplemental character
+ if (XMLChar.isHighSurrogate(c) && i < datalength) {
+ char c2 = dataarray[i++];
+ if (XMLChar.isLowSurrogate(c2) &&
+ XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) {
+ continue;
+ }
+ }
+ // Note: The key InvalidCharInCDSect from XMLMessages.properties
+ // is being used to obtain the message and DOM error type
+ // "wf-invalid-character" is used. Also per DOM it is error but
+ // as per XML spec. it is fatal error
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.XML_DOMAIN,
+ "InvalidCharInCDSect",
+ new Object[]{Integer.toString(c, 16)});
+ reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
+ }
+ else if (c==']') {
+ int count = i;
+ if ( count< datalength && dataarray[count]==']' ) {
+ while (++count < datalength && dataarray[count]==']' ) {
+ // do nothing
+ }
+ if ( count < datalength && dataarray[count]=='>' ) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, "CDEndInContent", null);
+ reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
+ }
+ }
+
+ }
+ }
+ } // end-else fDocument.isXMLVersion()
+
+ } // isCDataWF
+
+ /**
+ * NON-DOM: check for valid XML characters as per the XML version
+ * @param datavalue
+ * @param isXML11Version = true if XML 1.1
+ */
+ public static final void isXMLCharWF(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator,
+ String datavalue, boolean isXML11Version)
+ {
+ if ( datavalue == null || (datavalue.length() == 0) ) {
+ return;
+ }
+
+ char [] dataarray = datavalue.toCharArray();
+ int datalength = dataarray.length;
+
+ // version of the document is XML 1.1
+ if(isXML11Version){
+ //we need to check all characters as per production rules of XML11
+ int i = 0 ;
+ while (i < datalength) {
+ if(XML11Char.isXML11Invalid(dataarray[i++])){
+ // check if this is a supplemental character
+ char ch = dataarray[i-1];
+ if (XMLChar.isHighSurrogate(ch) && i < datalength) {
+ char ch2 = dataarray[i++];
+ if (XMLChar.isLowSurrogate(ch2) &&
+ XMLChar.isSupplemental(XMLChar.supplemental(ch, ch2))) {
+ continue;
+ }
+ }
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN, "InvalidXMLCharInDOM",
+ new Object[]{Integer.toString(dataarray[i-1], 16)});
+ reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR,
+ "wf-invalid-character");
+ }
+ }
+ } // version of the document is XML 1.0
+ else{
+ // we need to check all characters as per production rules of XML 1.0
+ int i = 0 ;
+ while (i < datalength) {
+ if( XMLChar.isInvalid(dataarray[i++]) ) {
+ // check if this is a supplemental character
+ char ch = dataarray[i-1];
+ if (XMLChar.isHighSurrogate(ch) && i < datalength) {
+ char ch2 = dataarray[i++];
+ if (XMLChar.isLowSurrogate(ch2) &&
+ XMLChar.isSupplemental(XMLChar.supplemental(ch, ch2))) {
+ continue;
+ }
+ }
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN, "InvalidXMLCharInDOM",
+ new Object[]{Integer.toString(dataarray[i-1], 16)});
+ reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR,
+ "wf-invalid-character");
+ }
+ }
+ } // end-else fDocument.isXMLVersion()
+
+ } // isXMLCharWF
+
+ /**
+ * NON-DOM: check if value of the comment is well-formed
+ * @param datavalue
+ * @param isXML11Version = true if XML 1.1
+ */
+ public static final void isCommentWF(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator,
+ String datavalue, boolean isXML11Version)
+ {
+ if ( datavalue == null || (datavalue.length() == 0) ) {
+ return;
+ }
+
+ char [] dataarray = datavalue.toCharArray();
+ int datalength = dataarray.length ;
+
+ // version of the document is XML 1.1
+ if (isXML11Version) {
+ // we need to check all chracters as per production rules of XML11
+ int i = 0 ;
+ while (i < datalength){
+ char c = dataarray[i++];
+ if ( XML11Char.isXML11Invalid(c) ) {
+ // check if this is a supplemental character
+ if (XMLChar.isHighSurrogate(c) && i < datalength) {
+ char c2 = dataarray[i++];
+ if (XMLChar.isLowSurrogate(c2) &&
+ XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) {
+ continue;
+ }
+ }
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,
+ "InvalidCharInComment",
+ new Object [] {Integer.toString(dataarray[i-1], 16)});
+ reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
+ }
+ else if (c == '-' && i < datalength && dataarray[i] == '-') {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,
+ "DashDashInComment", null);
+ // invalid: '--' in comment
+ reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
+ }
+ }
+ } // version of the document is XML 1.0
+ else {
+ // we need to check all chracters as per production rules of XML 1.0
+ int i = 0;
+ while (i < datalength){
+ char c = dataarray[i++];
+ if( XMLChar.isInvalid(c) ){
+ // check if this is a supplemental character
+ if (XMLChar.isHighSurrogate(c) && i < datalength) {
+ char c2 = dataarray[i++];
+ if (XMLChar.isLowSurrogate(c2) &&
+ XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) {
+ continue;
+ }
+ }
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,
+ "InvalidCharInComment", new Object [] {Integer.toString(dataarray[i-1], 16)});
+ reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
+ }
+ else if (c == '-' && istrongly
+ * recommended that a locator be supplied that can
+ * at least report the system identifier of the
+ * document.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal entities or a document entity that is
+ * parsed from a java.io.Reader).
+ * @param namespaceContext
+ * The namespace context in effect at the
+ * start of this document.
+ * This object represents the current context.
+ * Implementors of this class are responsible
+ * for copying the namespace bindings from the
+ * the current context (and its parent contexts)
+ * if that information is important.
+ *
+ * @param augs Additional information that may include infoset augmentations
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void startDocument(XMLLocator locator, String encoding,
+ NamespaceContext namespaceContext,
+ Augmentations augs)
+ throws XNIException{
+ }
+
+ /**
+ * Notifies of the presence of an XMLDecl line in the document. If
+ * present, this method will be called immediately following the
+ * startDocument call.
+ *
+ * @param version The XML version.
+ * @param encoding The IANA encoding name of the document, or null if
+ * not specified.
+ * @param standalone The standalone value, or null if not specified.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void xmlDecl(String version, String encoding, String standalone, Augmentations augs)
+ throws XNIException{
+ }
+
+ /**
+ * Notifies of the presence of the DOCTYPE line in the document.
+ *
+ * @param rootElement
+ * The name of the root element.
+ * @param publicId The public identifier if an external DTD or null
+ * if the external DTD is specified using SYSTEM.
+ * @param systemId The system identifier if an external DTD, null
+ * otherwise.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs)
+ throws XNIException{
+ }
+
+ /**
+ * A comment.
+ *
+ * @param text The text in the comment.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by application to signal an error.
+ */
+ public void comment(XMLString text, Augmentations augs) throws XNIException{
+ }
+
+ /**
+ * A processing instruction. Processing instructions consist of a
+ * target name and, optionally, text data. The data is only meaningful
+ * to the application.
+ *
+ * Typically, a processing instruction's data will contain a series
+ * of pseudo-attributes. These pseudo-attributes follow the form of
+ * element attributes but are not parsed or presented
+ * to the application as anything other than text. The application is
+ * responsible for parsing the data.
+ *
+ * @param target The target.
+ * @param data The data or null if none specified.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void processingInstruction(String target, XMLString data, Augmentations augs)
+ throws XNIException{
+ }
+
+ /**
+ * The start of an element.
+ *
+ * @param element The name of the element.
+ * @param attributes The element attributes.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
+ throws XNIException {
+ Element currentElement = (Element) fCurrentNode;
+ int attrCount = attributes.getLength();
+ if (DEBUG_EVENTS) {
+ System.out.println("==>startElement: " +element+
+ " attrs.length="+attrCount);
+ }
+
+ for (int i = 0; i < attrCount; i++) {
+ attributes.getName(i, fAttrQName);
+ Attr attr = null;
+
+ attr = currentElement.getAttributeNodeNS(fAttrQName.uri, fAttrQName.localpart);
+ if (attr == null) {
+ // Must be a non-namespace aware DOM Level 1 node.
+ attr = currentElement.getAttributeNode(fAttrQName.rawname);
+ }
+ AttributePSVI attrPSVI =
+ (AttributePSVI) attributes.getAugmentations(i).getItem(Constants.ATTRIBUTE_PSVI);
+
+ if (attrPSVI != null) {
+ //REVISIT: instead we should be using augmentations:
+ // to set/retrieve Id attributes
+ XSTypeDefinition decl = attrPSVI.getMemberTypeDefinition();
+ boolean id = false;
+ if (decl != null) {
+ id = ((XSSimpleType)decl).isIDType();
+ }
+ else {
+ decl = attrPSVI.getTypeDefinition();
+ if (decl != null) {
+ id = ((XSSimpleType)decl).isIDType();
+ }
+ }
+ if (id) {
+ ((ElementImpl)currentElement).setIdAttributeNode(attr, true);
+ }
+
+ if (fPSVI) {
+ ((PSVIAttrNSImpl) attr).setPSVI(attrPSVI);
+ }
+
+ // Updating the TypeInfo for this attribute.
+ ((AttrImpl) attr).setType(decl);
+
+ if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
+ // datatype-normalization
+ // NOTE: The specified value MUST be set after we set
+ // the node value because that turns the "specified"
+ // flag to "true" which may overwrite a "false"
+ // value from the attribute list.
+ final String normalizedValue = attrPSVI.getSchemaNormalizedValue();
+ if (normalizedValue != null) {
+ boolean specified = attr.getSpecified();
+ attr.setValue(normalizedValue);
+ if (!specified) {
+ ((AttrImpl) attr).setSpecified(specified);
+ }
+ }
+ }
+ }
+ else { // DTD
+ String type = null;
+ boolean isDeclared = Boolean.TRUE.equals(attributes.getAugmentations(i).getItem (Constants.ATTRIBUTE_DECLARED));
+ // For DOM Level 3 TypeInfo, the type name must
+ // be null if this attribute has not been declared
+ // in the DTD.
+ if (isDeclared) {
+ type = attributes.getType(i);
+ if ("ID".equals (type)) {
+ ((ElementImpl) currentElement).setIdAttributeNode(attr, true);
+ }
+ }
+ // Updating the TypeInfo for this attribute.
+ ((AttrImpl) attr).setType(type);
+ }
+ }
+ }
+
+
+ /**
+ * An empty element.
+ *
+ * @param element The name of the element.
+ * @param attributes The element attributes.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
+ throws XNIException {
+ if (DEBUG_EVENTS) {
+ System.out.println("==>emptyElement: " +element);
+ }
+
+ startElement(element, attributes, augs);
+ endElement(element, augs);
+ }
+
+ /**
+ * This method notifies the start of a general entity.
+ *
+ * Note: This method is not called for entity references
+ * appearing as part of attribute values.
+ *
+ * @param name The name of the general entity.
+ * @param identifier The resource identifier.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal entities or a document entity that is
+ * parsed from a java.io.Reader).
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException Thrown by handler to signal an error.
+ */
+ public void startGeneralEntity(String name,
+ XMLResourceIdentifier identifier,
+ String encoding,
+ Augmentations augs) throws XNIException{
+ }
+
+ /**
+ * Notifies of the presence of a TextDecl line in an entity. If present,
+ * this method will be called immediately following the startEntity call.
+ *
+ * Note: This method will never be called for the
+ * document entity; it is only called for external general entities
+ * referenced in document content.
+ *
+ * Note: This method is not called for entity references
+ * appearing as part of attribute values.
+ *
+ * @param version The XML version, or null if not specified.
+ * @param encoding The IANA encoding name of the entity.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void textDecl(String version, String encoding, Augmentations augs) throws XNIException{
+ }
+
+ /**
+ * This method notifies the end of a general entity.
+ *
+ * Note: This method is not called for entity references
+ * appearing as part of attribute values.
+ *
+ * @param name The name of the entity.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void endGeneralEntity(String name, Augmentations augs) throws XNIException{
+ }
+
+ /**
+ * Character content.
+ *
+ * @param text The content.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void characters(XMLString text, Augmentations augs) throws XNIException{
+ }
+
+ /**
+ * Ignorable whitespace. For this method to be called, the document
+ * source must have some way of determining that the text containing
+ * only whitespace characters should be considered ignorable. For
+ * example, the validator can determine if a length of whitespace
+ * characters in the document are ignorable based on the element
+ * content model.
+ *
+ * @param text The ignorable whitespace.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException{
+ fAllWhitespace = true;
+ }
+
+ /**
+ * The end of an element.
+ *
+ * @param element The name of the element.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void endElement(QName element, Augmentations augs) throws XNIException {
+ if (DEBUG_EVENTS) {
+ System.out.println("==>endElement: " + element);
+ }
+
+ if (augs != null) {
+ ElementPSVI elementPSVI = (ElementPSVI) augs.getItem(Constants.ELEMENT_PSVI);
+ if (elementPSVI != null) {
+ ElementImpl elementNode = (ElementImpl) fCurrentNode;
+ if (fPSVI) {
+ ((PSVIElementNSImpl) fCurrentNode).setPSVI(elementPSVI);
+ }
+ // Updating the TypeInfo for this element.
+ if (elementNode instanceof ElementNSImpl) {
+ XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
+ if (type == null) {
+ type = elementPSVI.getTypeDefinition();
+ }
+ ((ElementNSImpl) elementNode).setType(type);
+ }
+ // include element default content (if one is available)
+ String normalizedValue = elementPSVI.getSchemaNormalizedValue();
+ if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
+ if (normalizedValue !=null)
+ elementNode.setTextContent(normalizedValue);
+ }
+ else {
+ // NOTE: this is a hack: it is possible that DOM had an empty element
+ // and validator sent default value using characters(), which we don't
+ // implement. Thus, here we attempt to add the default value.
+ String text = elementNode.getTextContent();
+ if (text.length() == 0) {
+ // default content could be provided
+ if (normalizedValue !=null)
+ elementNode.setTextContent(normalizedValue);
+ }
+ }
+ return;
+ }
+ }
+ // DTD; elements have no type.
+ if (fCurrentNode instanceof ElementNSImpl) {
+ ((ElementNSImpl) fCurrentNode).setType(null);
+ }
+ }
+
+
+ /**
+ * The start of a CDATA section.
+ *
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void startCDATA(Augmentations augs) throws XNIException{
+ }
+
+ /**
+ * The end of a CDATA section.
+ *
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void endCDATA(Augmentations augs) throws XNIException{
+ }
+
+ /**
+ * The end of the document.
+ *
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void endDocument(Augmentations augs) throws XNIException{
+ }
+
+
+ /** Sets the document source. */
+ public void setDocumentSource(XMLDocumentSource source){
+ }
+
+
+ /** Returns the document source. */
+ public XMLDocumentSource getDocumentSource(){
+ return null;
+ }
+
+
+} // DOMNormalizer class
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DOMOutputImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DOMOutputImpl.java
new file mode 100644
index 0000000..0da8f79
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DOMOutputImpl.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.OutputStream;
+import java.io.Writer;
+
+import org.w3c.dom.ls.LSOutput;
+
+/**
+ * This class represents an output destination for data.
+ * This interface allows an application to encapsulate information about an
+ * output destination in a single object, which may include a URI, a byte stream
+ * (possibly with a specifiedencoding), a base URI, and/or a character stream.
+ * The exact definitions of a byte stream and a character stream are binding
+ * dependent.
+ * The application is expected to provide objects that implement this interface
+ * whenever such objects are needed. The application can either provide its
+ * own objects that implement this interface, or it can use the generic factory
+ * method DOMImplementationLS.createLSOutput() to create objects that
+ * implement this interface.
+ * The DOMSerializer will use the LSOutput object to determine where to
+ * serialize the output to. The DOMSerializer will look at the different
+ * outputs specified in the LSOutput in the following order to know which one
+ * to output to, the first one that data can be output to will be used:
+ * 1.LSOutput.characterStream
+ * 2.LSOutput.byteStream
+ * 3.LSOutput.systemId
+ * LSOutput objects belong to the application. The DOM implementation will
+ * never modify them (though it may make copies and modify the copies,
+ * if necessary).
+ *
+ * @xerces.internal
+ *
+ * @author Arun Yadav, Sun Microsytems
+ * @author Gopal Sharma, Sun Microsystems
+ **/
+
+public class DOMOutputImpl implements LSOutput {
+
+ protected Writer fCharStream = null;
+ protected OutputStream fByteStream = null;
+ protected String fSystemId = null;
+ protected String fEncoding = null;
+
+ /**
+ * Default Constructor
+ */
+ public DOMOutputImpl() {}
+
+ /**
+ * An attribute of a language and binding dependent type that represents a
+ * writable stream of bytes. If the application knows the character encoding
+ * of the byte stream, it should set the encoding attribute. Setting the
+ * encoding in this way will override any encoding specified in an XML
+ * declaration in the data.
+ */
+
+ public Writer getCharacterStream(){
+ return fCharStream;
+ };
+
+ /**
+ * An attribute of a language and binding dependent type that represents a
+ * writable stream of bytes. If the application knows the character encoding
+ * of the byte stream, it should set the encoding attribute. Setting the
+ * encoding in this way will override any encoding specified in an XML
+ * declaration in the data.
+ */
+
+ public void setCharacterStream(Writer characterStream){
+ fCharStream = characterStream;
+ };
+
+ /**
+ * Depending on the language binding in use, this attribute may not be
+ * available. An attribute of a language and binding dependent type that
+ * represents a writable stream to which 16-bit units can be output. The
+ * application must encode the stream using UTF-16 (defined in [Unicode] and
+ * Amendment 1 of [ISO/IEC 10646]).
+ */
+
+ public OutputStream getByteStream(){
+ return fByteStream;
+ };
+
+ /**
+ * Depending on the language binding in use, this attribute may not be
+ * available. An attribute of a language and binding dependent type that
+ * represents a writable stream to which 16-bit units can be output. The
+ * application must encode the stream using UTF-16 (defined in [Unicode] and
+ * Amendment 1 of [ISO/IEC 10646]).
+ */
+
+ public void setByteStream(OutputStream byteStream){
+ fByteStream = byteStream;
+ };
+
+ /**
+ * The system identifier, a URI reference [IETF RFC 2396], for this output
+ * destination. If the application knows the character encoding of the
+ * object pointed to by the system identifier, it can set the encoding
+ * using the encoding attribute. If the system ID is a relative URI
+ * reference (see section 5 in [IETF RFC 2396]), the behavior is
+ * implementation dependent.
+ */
+
+ public String getSystemId(){
+ return fSystemId;
+ };
+
+ /**
+ * The system identifier, a URI reference [IETF RFC 2396], for this output
+ * destination. If the application knows the character encoding of the
+ * object pointed to by the system identifier, it can set the encoding
+ * using the encoding attribute. If the system ID is a relative URI
+ * reference (see section 5 in [IETF RFC 2396]), the behavior is
+ * implementation dependent.
+ */
+
+ public void setSystemId(String systemId){
+ fSystemId = systemId;
+ };
+
+ /**
+ * The character encoding, if known. The encoding must be a string
+ * acceptable for an XML encoding declaration ([XML 1.0] section 4.3.3
+ * "Character Encoding in Entities"). This attribute has no effect when the
+ * application provides a character stream or string data. For other sources
+ * of input, an encoding specified by means of this attribute will override
+ * any encoding specified in the XML declaration or the Text declaration, or
+ * an encoding obtained from a higher level protocol, such as HTTP
+ * [IETF RFC 2616].
+ */
+
+ public String getEncoding(){
+ return fEncoding;
+ };
+
+ /**
+ * The character encoding, if known. The encoding must be a string
+ * acceptable for an XML encoding declaration ([XML 1.0] section 4.3.3
+ * "Character Encoding in Entities"). This attribute has no effect when the
+ * application provides a character stream or string data. For other sources
+ * of input, an encoding specified by means of this attribute will override
+ * any encoding specified in the XML declaration or the Text declaration, or
+ * an encoding obtained from a higher level protocol, such as HTTP
+ * [IETF RFC 2616].
+ */
+
+ public void setEncoding(String encoding){
+ fEncoding = encoding;
+ };
+
+}//DOMOutputImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DOMStringListImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DOMStringListImpl.java
new file mode 100644
index 0000000..015aceb
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DOMStringListImpl.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+import org.w3c.dom.DOMStringList;
+
+/**
+ * DOM Level 3
+ *
+ * This class implements the DOM Level 3 Core interface DOMStringList.
+ *
+ * @xerces.internal
+ *
+ * @author Neil Delima, IBM
+ */
+public class DOMStringListImpl implements DOMStringList {
+
+ // A collection of DOMString values
+ private final ArrayList fStrings;
+
+ /**
+ * Construct an empty list of DOMStringListImpl
+ */
+ public DOMStringListImpl() {
+ fStrings = new ArrayList();
+ }
+
+ /**
+ * Construct a DOMStringListImpl from an ArrayList
+ */
+ public DOMStringListImpl(ArrayList params) {
+ fStrings = params;
+ }
+
+ /**
+ * Construct a DOMStringListImpl from a Vector
+ */
+ public DOMStringListImpl(Vector params) {
+ fStrings = new ArrayList(params);
+ }
+
+ /**
+ * @see org.w3c.dom.DOMStringList#item(int)
+ */
+ public String item(int index) {
+ final int length = getLength();
+ if (index >= 0 && index < length) {
+ return (String) fStrings.get(index);
+ }
+ return null;
+ }
+
+ /**
+ * @see org.w3c.dom.DOMStringList#getLength()
+ */
+ public int getLength() {
+ return fStrings.size();
+ }
+
+ /**
+ * @see org.w3c.dom.DOMStringList#contains(String)
+ */
+ public boolean contains(String param) {
+ return fStrings.contains(param);
+ }
+
+ /**
+ * DOM Internal:
+ * Add a DOMString to the list.
+ *
+ * @param param A string to add to the list
+ */
+ public void add(String param) {
+ fStrings.add(param);
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DOMXSImplementationSourceImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DOMXSImplementationSourceImpl.java
new file mode 100644
index 0000000..249210b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DOMXSImplementationSourceImpl.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.util.ArrayList;
+
+import org.apache.xerces.impl.xs.XSImplementationImpl;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.DOMImplementationList;
+
+/**
+ * Allows to retrieve XSImplementation , DOM Level 3 Core and LS implementations
+ * and PSVI implementation.
+ * See also the Document Object Model (DOM) Level 3 Core Specification.
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani, IBM
+ * @version $Id$
+ */
+public class DOMXSImplementationSourceImpl
+ extends DOMImplementationSourceImpl {
+
+ /**
+ * A method to request a DOM implementation.
+ * @param features A string that specifies which features are required.
+ * This is a space separated list in which each feature is specified
+ * by its name optionally followed by a space and a version number.
+ * This is something like: "XML 1.0 Traversal Events 2.0"
+ * @return An implementation that has the desired features, or
+ * null if this source has none.
+ */
+ public DOMImplementation getDOMImplementation(String features) {
+ DOMImplementation impl = super.getDOMImplementation(features);
+ if (impl != null){
+ return impl;
+ }
+ // if not try the PSVIDOMImplementation
+ impl = PSVIDOMImplementationImpl.getDOMImplementation();
+ if (testImpl(impl, features)) {
+ return impl;
+ }
+ // if not try the XSImplementation
+ impl = XSImplementationImpl.getDOMImplementation();
+ if (testImpl(impl, features)) {
+ return impl;
+ }
+
+ return null;
+ }
+
+ /**
+ * A method to request a list of DOM implementations that support the
+ * specified features and versions, as specified in .
+ * @param features A string that specifies which features and versions
+ * are required. This is a space separated list in which each feature
+ * is specified by its name optionally followed by a space and a
+ * version number. This is something like: "XML 3.0 Traversal +Events
+ * 2.0"
+ * @return A list of DOM implementations that support the desired
+ * features.
+ */
+ public DOMImplementationList getDOMImplementationList(String features) {
+ final ArrayList implementations = new ArrayList();
+
+ // first check whether the CoreDOMImplementation would do
+ DOMImplementationList list = super.getDOMImplementationList(features);
+ // Add core DOMImplementations
+ for (int i = 0; i < list.getLength(); ++i) {
+ implementations.add(list.item(i));
+ }
+
+ DOMImplementation impl = PSVIDOMImplementationImpl.getDOMImplementation();
+ if (testImpl(impl, features)) {
+ implementations.add(impl);
+ }
+
+ impl = XSImplementationImpl.getDOMImplementation();
+ if (testImpl(impl, features)) {
+ implementations.add(impl);
+ }
+ return new DOMImplementationListImpl(implementations);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeepNodeListImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeepNodeListImpl.java
new file mode 100644
index 0000000..f3b65d7
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeepNodeListImpl.java
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.util.ArrayList;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * This class implements the DOM's NodeList behavior for
+ * Element.getElementsByTagName()
+ *
+ * The DOM describes NodeList as follows:
+ *
+ * 1) It may represent EITHER nodes scattered through a subtree (when
+ * returned by Element.getElementsByTagName), or just the immediate
+ * children (when returned by Node.getChildNodes). The latter is easy,
+ * but the former (which this class addresses) is more challenging.
+ *
+ * 2) Its behavior is "live" -- that is, it always reflects the
+ * current state of the document tree. To put it another way, the
+ * NodeLists obtained before and after a series of insertions and
+ * deletions are effectively identical (as far as the user is
+ * concerned, the former has been dynamically updated as the changes
+ * have been made).
+ *
+ * 3) Its API accesses individual nodes via an integer index, with the
+ * listed nodes numbered sequentially in the order that they were
+ * found during a preorder depth-first left-to-right search of the tree.
+ * (Of course in the case of getChildNodes, depth is not involved.) As
+ * nodes are inserted or deleted in the tree, and hence the NodeList,
+ * the numbering of nodes that follow them in the NodeList will
+ * change.
+ *
+ * It is rather painful to support the latter two in the
+ * getElementsByTagName case. The current solution is for Nodes to
+ * maintain a change count (eventually that may be a Digest instead),
+ * which the NodeList tracks and uses to invalidate itself.
+ *
+ * Unfortunately, this does _not_ respond efficiently in the case that
+ * the dynamic behavior was supposed to address: scanning a tree while
+ * it is being extended. That requires knowing which subtrees have
+ * changed, which can become an arbitrarily complex problem.
+ *
+ * We save some work by filling the ArrayList only as we access the
+ * item()s... but I suspect the same users who demanded index-based
+ * access will also start by doing a getLength() to control their loop,
+ * blowing this optimization out of the water.
+ *
+ * NOTE: Level 2 of the DOM will probably _not_ use NodeList for its
+ * extended search mechanisms, partly for the reasons just discussed.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DeepNodeListImpl
+ implements NodeList {
+
+ //
+ // Data
+ //
+
+ protected NodeImpl rootNode; // Where the search started
+ protected String tagName; // Or "*" to mean all-tags-acceptable
+ protected int changes=0;
+ protected ArrayList nodes;
+
+ protected String nsName;
+ protected boolean enableNS = false;
+
+ //
+ // Constructors
+ //
+
+ /** Constructor. */
+ public DeepNodeListImpl(NodeImpl rootNode, String tagName) {
+ this.rootNode = rootNode;
+ this.tagName = tagName;
+ nodes = new ArrayList();
+ }
+
+ /** Constructor for Namespace support. */
+ public DeepNodeListImpl(NodeImpl rootNode,
+ String nsName, String tagName) {
+ this(rootNode, tagName);
+ this.nsName = (nsName != null && nsName.length() != 0) ? nsName : null;
+ enableNS = true;
+ }
+
+ //
+ // NodeList methods
+ //
+
+ /** Returns the length of the node list. */
+ public int getLength() {
+ // Preload all matching elements. (Stops when we run out of subtree!)
+ item(java.lang.Integer.MAX_VALUE);
+ return nodes.size();
+ }
+
+ /** Returns the node at the specified index. */
+ public Node item(int index) {
+ Node thisNode;
+
+ // Tree changed. Do it all from scratch!
+ if (rootNode.changes() != changes) {
+ nodes = new ArrayList();
+ changes = rootNode.changes();
+ }
+
+ // In the cache
+ final int currentSize = nodes.size();
+ if (index < currentSize) {
+ return (Node)nodes.get(index);
+ }
+ // Not yet seen
+ else {
+
+ // Pick up where we left off (Which may be the beginning)
+ if (currentSize == 0) {
+ thisNode = rootNode;
+ }
+ else {
+ thisNode = (NodeImpl)(nodes.get(currentSize - 1));
+ }
+
+ // Add nodes up to the one we're looking for
+ while (thisNode != null && index >= nodes.size()) {
+ thisNode = nextMatchingElementAfter(thisNode);
+ if (thisNode != null) {
+ nodes.add(thisNode);
+ }
+ }
+
+ // Either what we want, or null (not avail.)
+ return thisNode;
+ }
+
+ } // item(int):Node
+
+ //
+ // Protected methods (might be overridden by an extending DOM)
+ //
+
+ /**
+ * Iterative tree-walker. When you have a Parent link, there's often no
+ * need to resort to recursion. NOTE THAT only Element nodes are matched
+ * since we're specifically supporting getElementsByTagName().
+ */
+ protected Node nextMatchingElementAfter(Node current) {
+
+ Node next;
+ while (current != null) {
+ // Look down to first child.
+ if (current.hasChildNodes()) {
+ current = (current.getFirstChild());
+ }
+
+ // Look right to sibling (but not from root!)
+ else if (current != rootNode && null != (next = current.getNextSibling())) {
+ current = next;
+ }
+
+ // Look up and right (but not past root!)
+ else {
+ next = null;
+ for (; current != rootNode; // Stop when we return to starting point
+ current = current.getParentNode()) {
+
+ next = current.getNextSibling();
+ if (next != null)
+ break;
+ }
+ current = next;
+ }
+
+ // Have we found an Element with the right tagName?
+ // ("*" matches anything.)
+ if (current != rootNode
+ && current != null
+ && current.getNodeType() == Node.ELEMENT_NODE) {
+ if (!enableNS) {
+ if (tagName.equals("*") ||
+ ((ElementImpl) current).getTagName().equals(tagName))
+ {
+ return current;
+ }
+ } else {
+ // DOM2: Namespace logic.
+ if (tagName.equals("*")) {
+ if (nsName != null && nsName.equals("*")) {
+ return current;
+ } else {
+ ElementImpl el = (ElementImpl) current;
+ if ((nsName == null
+ && el.getNamespaceURI() == null)
+ || (nsName != null
+ && nsName.equals(el.getNamespaceURI())))
+ {
+ return current;
+ }
+ }
+ } else {
+ ElementImpl el = (ElementImpl) current;
+ if (el.getLocalName() != null
+ && el.getLocalName().equals(tagName)) {
+ if (nsName != null && nsName.equals("*")) {
+ return current;
+ } else {
+ if ((nsName == null
+ && el.getNamespaceURI() == null)
+ || (nsName != null &&
+ nsName.equals(el.getNamespaceURI())))
+ {
+ return current;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Otherwise continue walking the tree
+ }
+
+ // Fell out of tree-walk; no more instances found
+ return null;
+
+ } // nextMatchingElementAfter(int):Node
+
+} // class DeepNodeListImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredAttrImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredAttrImpl.java
new file mode 100644
index 0000000..f2d93f3
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredAttrImpl.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * WARNING: because java doesn't support multi-inheritance some code is
+ * duplicated. If you're changing this file you probably want to change
+ * DeferredAttrNSImpl.java at the same time.
+ */
+
+package org.apache.xerces.dom;
+
+/**
+ * Attribute represents an XML-style attribute of an
+ * Element. Typically, the allowable values are controlled by its
+ * declaration in the Document Type Definition (DTD) governing this
+ * kind of document.
+ *
+ * If the attribute has not been explicitly assigned a value, but has
+ * been declared in the DTD, it will exist and have that default. Only
+ * if neither the document nor the DTD specifies a value will the
+ * Attribute really be considered absent and have no value; in that
+ * case, querying the attribute will return null.
+ *
+ * Attributes may have multiple children that contain their data. (XML
+ * allows attributes to contain entity references, and tokenized
+ * attribute types such as NMTOKENS may have a child for each token.)
+ * For convenience, the Attribute object's getValue() method returns
+ * the string version of the attribute's value.
+ *
+ * Attributes are not children of the Elements they belong to, in the
+ * usual sense, and have no valid Parent reference. However, the spec
+ * says they _do_ belong to a specific Element, and an INUSE exception
+ * is to be thrown if the user attempts to explicitly share them
+ * between elements.
+ *
+ * Note that Elements do not permit attributes to appear to be shared
+ * (see the INUSE exception), so this object's mutability is
+ * officially not an issue.
+ *
+ * DeferredAttrImpl inherits from AttrImpl which does not support
+ * Namespaces. DeferredAttrNSImpl, which inherits from AttrNSImpl, does.
+ * @see DeferredAttrNSImpl
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ * @author Arnaud Le Hors, IBM
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public final class DeferredAttrImpl
+ extends AttrImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 6903232312469148636L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here.
+ * All other data, can be requested from the ownerDocument via the index.
+ */
+ DeferredAttrImpl(DeferredDocumentImpl ownerDocument, int nodeIndex) {
+ super(ownerDocument, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncData(true);
+ needsSyncChildren(true);
+
+ } // (DeferredDocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /** Synchronizes the data (name and value) for fast nodes. */
+ protected void synchronizeData() {
+
+ // no need to sync in the future
+ needsSyncData(false);
+
+ // fluff data
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) ownerDocument();
+ name = ownerDocument.getNodeName(fNodeIndex);
+ int extra = ownerDocument.getNodeExtra(fNodeIndex);
+ isSpecified((extra & SPECIFIED) != 0);
+ isIdAttribute((extra & ID) != 0);
+
+ int extraNode = ownerDocument.getLastChild(fNodeIndex);
+ type = ownerDocument.getTypeInfo(extraNode);
+ } // synchronizeData()
+
+ /**
+ * Synchronizes the node's children with the internal structure.
+ * Fluffing the children at once solves a lot of work to keep
+ * the two structures in sync. The problem gets worse when
+ * editing the tree -- this makes it a lot easier.
+ */
+ protected void synchronizeChildren() {
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) ownerDocument();
+ ownerDocument.synchronizeChildren(this, fNodeIndex);
+ } // synchronizeChildren()
+
+} // class DeferredAttrImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredAttrNSImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredAttrNSImpl.java
new file mode 100644
index 0000000..45db1f8
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredAttrNSImpl.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * WARNING: because java doesn't support multi-inheritance some code is
+ * duplicated. If you're changing this file you probably want to change
+ * DeferredAttrImpl.java at the same time.
+ */
+
+
+package org.apache.xerces.dom;
+
+/**
+ * DeferredAttrNSImpl is to AttrNSImpl, what DeferredAttrImpl is to
+ * AttrImpl.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ * @author Arnaud Le Hors, IBM
+ * @version $Id$
+ * @see DeferredAttrImpl
+ */
+public final class DeferredAttrNSImpl
+ extends AttrNSImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 6074924934945957154L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here.
+ * All other data, can be requested from the ownerDocument via the index.
+ */
+ DeferredAttrNSImpl(DeferredDocumentImpl ownerDocument, int nodeIndex) {
+ super(ownerDocument, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncData(true);
+ needsSyncChildren(true);
+
+ } // (DeferredDocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /** Synchronizes the data (name and value) for fast nodes. */
+ protected void synchronizeData() {
+
+ // no need to sync in the future
+ needsSyncData(false);
+
+ // fluff data
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) ownerDocument();
+ name = ownerDocument.getNodeName(fNodeIndex);
+
+ // extract prefix and local part from QName
+ int index = name.indexOf(':');
+ if (index < 0) {
+ localName = name;
+ }
+ else {
+ localName = name.substring(index + 1);
+ }
+
+ int extra = ownerDocument.getNodeExtra(fNodeIndex);
+ isSpecified((extra & SPECIFIED) != 0);
+ isIdAttribute((extra & ID) != 0);
+
+ namespaceURI = ownerDocument.getNodeURI(fNodeIndex);
+
+ int extraNode = ownerDocument.getLastChild(fNodeIndex);
+ type = ownerDocument.getTypeInfo(extraNode);
+ } // synchronizeData()
+
+ /**
+ * Synchronizes the node's children with the internal structure.
+ * Fluffing the children at once solves a lot of work to keep
+ * the two structures in sync. The problem gets worse when
+ * editing the tree -- this makes it a lot easier.
+ */
+ protected void synchronizeChildren() {
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) ownerDocument();
+ ownerDocument.synchronizeChildren(this, fNodeIndex);
+ } // synchronizeChildren()
+
+} // class DeferredAttrImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredCDATASectionImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredCDATASectionImpl.java
new file mode 100644
index 0000000..97da4ae
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredCDATASectionImpl.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+/**
+ * XML provides the CDATA markup to allow a region of text in which
+ * most of the XML delimiter recognition does not take place. This is
+ * intended to ease the task of quoting XML fragments and other
+ * programmatic information in a document's text without needing to
+ * escape these special characters. It's primarily a convenience feature
+ * for those who are hand-editing XML.
+ *
+ * CDATASection is an Extended DOM feature, and is not used in HTML
+ * contexts.
+ *
+ * Within the DOM, CDATASections are treated essentially as Text
+ * blocks. Their distinct type is retained in order to allow us to
+ * properly recreate the XML syntax when we write them out.
+ *
+ * Reminder: CDATA IS NOT A COMPLETELY GENERAL SOLUTION; it can't
+ * quote its own end-of-block marking. If you need to write out a
+ * CDATA that contains the ]]> sequence, it's your responsibility to
+ * split that string over two successive CDATAs at that time.
+ *
+ * CDATA does not participate in Element.normalize() processing.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DeferredCDATASectionImpl
+ extends CDATASectionImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 1983580632355645726L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here. All other data,
+ * can be requested from the ownerDocument via the index.
+ */
+ DeferredCDATASectionImpl(DeferredDocumentImpl ownerDocument, int nodeIndex) {
+ super(ownerDocument, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncData(true);
+
+ } // (DeferredDocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /** Synchronizes the data (name and value) for fast nodes. */
+ protected void synchronizeData() {
+
+ // no need to sync in the future
+ needsSyncData(false);
+
+ // fluff data
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) this.ownerDocument();
+ data = ownerDocument.getNodeValueString(fNodeIndex);
+
+ } // synchronizeData()
+
+} // class DeferredCDATASectionImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredCommentImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredCommentImpl.java
new file mode 100644
index 0000000..a5cbf76
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredCommentImpl.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+/**
+ * Represents an XML (or HTML) comment.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DeferredCommentImpl
+ extends CommentImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 6498796371083589338L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here. All other data,
+ * can be requested from the ownerDocument via the index.
+ */
+ DeferredCommentImpl(DeferredDocumentImpl ownerDocument, int nodeIndex) {
+ super(ownerDocument, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncData(true);
+
+ } // (DeferredDocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /** Synchronizes the data (name and value) for fast nodes. */
+ protected void synchronizeData() {
+
+ // no need to sync in the future
+ needsSyncData(false);
+
+ // fluff data
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) this.ownerDocument();
+ data = ownerDocument.getNodeValueString(fNodeIndex);
+
+ } // synchronizeData()
+
+} // class DeferredCommentImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredDOMImplementationImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredDOMImplementationImpl.java
new file mode 100644
index 0000000..6516fe0
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredDOMImplementationImpl.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.xerces.dom;
+
+import org.w3c.dom.DOMImplementation;
+
+/**
+ * This DOMImplementation class is description of a particular
+ * implementation of the Document Object Model. As such its data is
+ * static, shared by all instances of this implementation.
+ *
+ * This implementation simply extends DOMImplementationImpl to differentiate
+ * between the Deferred DOM Implementations and Non-Deferred DOM Implementations.
+ *
+ * @xerces.internal
+ *
+ * @author Neil Delima, IBM
+ *
+ * @version $Id$
+ */
+public class DeferredDOMImplementationImpl
+ extends DOMImplementationImpl {
+
+ //
+ // Data
+ //
+
+ // static
+
+ /** Dom implementation singleton. */
+ static final DeferredDOMImplementationImpl singleton = new DeferredDOMImplementationImpl();
+
+
+ //
+ // Public methods
+ //
+
+ /** NON-DOM: Obtain and return the single shared object */
+ public static DOMImplementation getDOMImplementation() {
+ return singleton;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredDocumentImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredDocumentImpl.java
new file mode 100644
index 0000000..781c11e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredDocumentImpl.java
@@ -0,0 +1,2155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.util.ArrayList;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * The Document interface represents the entire HTML or XML document.
+ * Conceptually, it is the root of the document tree, and provides the
+ * primary access to the document's data.
+ *
+ * Since elements, text nodes, comments, processing instructions,
+ * etc. cannot exist outside the context of a Document, the Document
+ * interface also contains the factory methods needed to create these
+ * objects. The Node objects created have a ownerDocument attribute
+ * which associates them with the Document within whose context they
+ * were created.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DeferredDocumentImpl
+ extends DocumentImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 5186323580749626857L;
+
+ // debugging
+
+ /** To include code for printing the ref count tables. */
+ private static final boolean DEBUG_PRINT_REF_COUNTS = false;
+
+ /** To include code for printing the internal tables. */
+ private static final boolean DEBUG_PRINT_TABLES = false;
+
+ /** To debug identifiers set to true and recompile. */
+ private static final boolean DEBUG_IDS = false;
+
+ // protected
+
+ /** Chunk shift. */
+ protected static final int CHUNK_SHIFT = 11; // 2^11 = 2k
+
+ /** Chunk size. */
+ protected static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
+
+ /** Chunk mask. */
+ protected static final int CHUNK_MASK = CHUNK_SIZE - 1;
+
+ /** Initial chunk size. */
+ protected static final int INITIAL_CHUNK_COUNT = (1 << (16 - CHUNK_SHIFT)); // 2^16 = 64k
+
+ //
+ // Data
+ //
+
+ // lazy-eval information
+ // To maximize memory consumption the actual semantic of these fields vary
+ // depending on the node type.
+
+ /** Node count. */
+ protected transient int fNodeCount = 0;
+
+ /** Node types. */
+ protected transient int fNodeType[][];
+
+ /** Node names. */
+ protected transient Object fNodeName[][];
+
+ /** Node values. */
+ protected transient Object fNodeValue[][];
+
+ /** Node parents. */
+ protected transient int fNodeParent[][];
+
+ /** Node first children. */
+ protected transient int fNodeLastChild[][];
+
+ /** Node prev siblings. */
+ protected transient int fNodePrevSib[][];
+
+ /** Node namespace URI. */
+ protected transient Object fNodeURI[][];
+
+ /** Extra data. */
+ protected transient int fNodeExtra[][];
+
+ /** Identifier count. */
+ protected transient int fIdCount;
+
+ /** Identifier name indexes. */
+ protected transient String fIdName[];
+
+ /** Identifier element indexes. */
+ protected transient int fIdElement[];
+
+ /** DOM2: For namespace support in the deferred case.
+ */
+ // Implementation Note: The deferred element and attribute must know how to
+ // interpret the int representing the qname.
+ protected boolean fNamespacesEnabled = false;
+
+ //
+ // private data
+ //
+ private transient final StringBuffer fBufferStr = new StringBuffer();
+ private transient final ArrayList fStrChunks = new ArrayList();
+
+ //
+ // Constructors
+ //
+
+ /**
+ * NON-DOM: Actually creating a Document is outside the DOM's spec,
+ * since it has to operate in terms of a particular implementation.
+ */
+ public DeferredDocumentImpl() {
+ this(false);
+ } // ()
+
+ /**
+ * NON-DOM: Actually creating a Document is outside the DOM's spec,
+ * since it has to operate in terms of a particular implementation.
+ */
+ public DeferredDocumentImpl(boolean namespacesEnabled) {
+ this(namespacesEnabled, false);
+ } // (boolean)
+
+ /** Experimental constructor. */
+ public DeferredDocumentImpl(boolean namespaces, boolean grammarAccess) {
+ super(grammarAccess);
+
+ needsSyncData(true);
+ needsSyncChildren(true);
+
+ fNamespacesEnabled = namespaces;
+
+ } // (boolean,boolean)
+
+ //
+ // Public methods
+ //
+
+ /**
+ * Retrieve information describing the abilities of this particular
+ * DOM implementation. Intended to support applications that may be
+ * using DOMs retrieved from several different sources, potentially
+ * with different underlying representations.
+ */
+ public DOMImplementation getImplementation() {
+ // Currently implemented as a singleton, since it's hardcoded
+ // information anyway.
+ return DeferredDOMImplementationImpl.getDOMImplementation();
+ }
+
+ /** Returns the cached parser.getNamespaces() value.*/
+ boolean getNamespacesEnabled() {
+ return fNamespacesEnabled;
+ }
+
+ void setNamespacesEnabled(boolean enable) {
+ fNamespacesEnabled = enable;
+ }
+
+ // internal factory methods
+
+ /** Creates a document node in the table. */
+ public int createDeferredDocument() {
+ int nodeIndex = createNode(Node.DOCUMENT_NODE);
+ return nodeIndex;
+ }
+
+ /** Creates a doctype. */
+ public int createDeferredDocumentType(String rootElementName,
+ String publicId, String systemId) {
+
+ // create node
+ int nodeIndex = createNode(Node.DOCUMENT_TYPE_NODE);
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+
+ // save name, public id, system id
+ setChunkValue(fNodeName, rootElementName, chunk, index);
+ setChunkValue(fNodeValue, publicId, chunk, index);
+ setChunkValue(fNodeURI, systemId, chunk, index);
+
+ // return node index
+ return nodeIndex;
+
+ } // createDeferredDocumentType(String,String,String):int
+
+ public void setInternalSubset(int doctypeIndex, String subset) {
+ int chunk = doctypeIndex >> CHUNK_SHIFT;
+ int index = doctypeIndex & CHUNK_MASK;
+
+ // create extra data node to store internal subset
+ int extraDataIndex = createNode(Node.DOCUMENT_TYPE_NODE);
+ int echunk = extraDataIndex >> CHUNK_SHIFT;
+ int eindex = extraDataIndex & CHUNK_MASK;
+ setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
+ setChunkValue(fNodeValue, subset, echunk, eindex);
+ }
+
+ /** Creates a notation in the table. */
+ public int createDeferredNotation(String notationName,
+ String publicId, String systemId, String baseURI) {
+
+ // create node
+ int nodeIndex = createNode(Node.NOTATION_NODE);
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+
+
+ // create extra data node
+ int extraDataIndex = createNode(Node.NOTATION_NODE);
+ int echunk = extraDataIndex >> CHUNK_SHIFT;
+ int eindex = extraDataIndex & CHUNK_MASK;
+
+ // save name, public id, system id, and notation name
+ setChunkValue(fNodeName, notationName, chunk, index);
+ setChunkValue(fNodeValue, publicId, chunk, index);
+ setChunkValue(fNodeURI, systemId, chunk, index);
+
+ // in extra data node set baseURI value
+ setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
+ setChunkValue(fNodeName, baseURI, echunk, eindex);
+
+ // return node index
+ return nodeIndex;
+
+ } // createDeferredNotation(String,String,String):int
+
+ /** Creates an entity in the table. */
+ public int createDeferredEntity(String entityName, String publicId,
+ String systemId, String notationName,
+ String baseURI) {
+ // create node
+ int nodeIndex = createNode(Node.ENTITY_NODE);
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+
+ // create extra data node
+ int extraDataIndex = createNode(Node.ENTITY_NODE);
+ int echunk = extraDataIndex >> CHUNK_SHIFT;
+ int eindex = extraDataIndex & CHUNK_MASK;
+
+ // save name, public id, system id, and notation name
+ setChunkValue(fNodeName, entityName, chunk, index);
+ setChunkValue(fNodeValue, publicId, chunk, index);
+ setChunkValue(fNodeURI, systemId, chunk, index);
+ setChunkIndex(fNodeExtra, extraDataIndex, chunk, index);
+ // set other values in the extra chunk
+ // notation
+ setChunkValue(fNodeName, notationName, echunk, eindex);
+ // version L3
+ setChunkValue(fNodeValue, null, echunk, eindex);
+ // encoding L3
+ setChunkValue(fNodeURI, null, echunk, eindex);
+
+
+ int extraDataIndex2 = createNode(Node.ENTITY_NODE);
+ int echunk2 = extraDataIndex2 >> CHUNK_SHIFT;
+ int eindex2 = extraDataIndex2 & CHUNK_MASK;
+
+ setChunkIndex(fNodeExtra, extraDataIndex2, echunk, eindex);
+
+ // baseURI
+ setChunkValue(fNodeName, baseURI, echunk2, eindex2);
+
+ // return node index
+ return nodeIndex;
+
+ } // createDeferredEntity(String,String,String,String):int
+
+ public String getDeferredEntityBaseURI (int entityIndex){
+ if (entityIndex != -1) {
+ int extraDataIndex = getNodeExtra(entityIndex, false);
+ extraDataIndex = getNodeExtra(extraDataIndex, false);
+ return getNodeName (extraDataIndex, false);
+ }
+ return null;
+ }
+
+ // DOM Level 3: setting encoding and version
+ public void setEntityInfo(int currentEntityDecl,
+ String version, String encoding){
+ int eNodeIndex = getNodeExtra(currentEntityDecl, false);
+ if (eNodeIndex !=-1) {
+ int echunk = eNodeIndex >> CHUNK_SHIFT;
+ int eindex = eNodeIndex & CHUNK_MASK;
+ setChunkValue(fNodeValue, version, echunk, eindex);
+ setChunkValue(fNodeURI, encoding, echunk, eindex);
+ }
+ }
+
+ // DOM Level 3: sets element TypeInfo
+ public void setTypeInfo(int elementNodeIndex, Object type) {
+ int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
+ int elementIndex = elementNodeIndex & CHUNK_MASK;
+ setChunkValue(fNodeValue, type, elementChunk, elementIndex);
+ }
+
+ /**
+ * DOM Internal
+ *
+ * An attribute specifying the actual encoding of this document. This is
+ * null otherwise.
+ * This attribute represents the property [character encoding scheme]
+ * defined in .
+ */
+ public void setInputEncoding(int currentEntityDecl, String value){
+ // get first extra data chunk
+ int nodeIndex = getNodeExtra(currentEntityDecl, false);
+ // get second extra data chunk
+ int extraDataIndex = getNodeExtra(nodeIndex, false);
+
+ int echunk = extraDataIndex >> CHUNK_SHIFT;
+ int eindex = extraDataIndex & CHUNK_MASK;
+
+ setChunkValue(fNodeValue, value, echunk, eindex);
+
+ }
+
+ /** Creates an entity reference node in the table. */
+ public int createDeferredEntityReference(String name, String baseURI) {
+
+ // create node
+ int nodeIndex = createNode(Node.ENTITY_REFERENCE_NODE);
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ setChunkValue(fNodeName, name, chunk, index);
+ setChunkValue(fNodeValue, baseURI, chunk, index);
+
+ // return node index
+ return nodeIndex;
+
+ } // createDeferredEntityReference(String):int
+
+
+ /**
+ * Creates an element node with a URI in the table and type information.
+ * @deprecated
+ */
+ public int createDeferredElement(String elementURI, String elementName,
+ Object type) {
+
+ // create node
+ int elementNodeIndex = createNode(Node.ELEMENT_NODE);
+ int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
+ int elementIndex = elementNodeIndex & CHUNK_MASK;
+ setChunkValue(fNodeName, elementName, elementChunk, elementIndex);
+ setChunkValue(fNodeURI, elementURI, elementChunk, elementIndex);
+ setChunkValue(fNodeValue, type, elementChunk, elementIndex);
+
+ // return node index
+ return elementNodeIndex;
+
+ } // createDeferredElement(String,String,Object):int
+
+ /**
+ * Creates an element node in the table.
+ * @deprecated
+ */
+ public int createDeferredElement(String elementName) {
+ return createDeferredElement(null, elementName);
+ }
+
+ /**
+ * Creates an element node with a URI in the table.
+ */
+ public int createDeferredElement(String elementURI, String elementName) {
+
+ // create node
+ int elementNodeIndex = createNode(Node.ELEMENT_NODE);
+ int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
+ int elementIndex = elementNodeIndex & CHUNK_MASK;
+ setChunkValue(fNodeName, elementName, elementChunk, elementIndex);
+ setChunkValue(fNodeURI, elementURI, elementChunk, elementIndex);
+
+ // return node index
+ return elementNodeIndex;
+
+ } // createDeferredElement(String,String):int
+
+
+ /**
+ * This method is used by the DOMParser to create attributes.
+ * @param elementNodeIndex
+ * @param attrName
+ * @param attrURI
+ * @param attrValue
+ * @param specified
+ * @param id
+ * @param type
+ * @return int
+ */
+ public int setDeferredAttribute(int elementNodeIndex,
+ String attrName,
+ String attrURI,
+ String attrValue,
+ boolean specified,
+ boolean id,
+ Object type) {
+
+ // create attribute
+ int attrNodeIndex = createDeferredAttribute(attrName, attrURI, attrValue, specified);
+ int attrChunk = attrNodeIndex >> CHUNK_SHIFT;
+ int attrIndex = attrNodeIndex & CHUNK_MASK;
+ // set attribute's parent to element
+ setChunkIndex(fNodeParent, elementNodeIndex, attrChunk, attrIndex);
+
+ int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
+ int elementIndex = elementNodeIndex & CHUNK_MASK;
+
+ // get element's last attribute
+ int lastAttrNodeIndex = getChunkIndex(fNodeExtra, elementChunk, elementIndex);
+ if (lastAttrNodeIndex != 0) {
+ // add link from new attribute to last attribute
+ setChunkIndex(fNodePrevSib, lastAttrNodeIndex, attrChunk, attrIndex);
+ }
+ // add link from element to new last attribute
+ setChunkIndex(fNodeExtra, attrNodeIndex, elementChunk, elementIndex);
+
+ int extra = getChunkIndex(fNodeExtra, attrChunk, attrIndex);
+ if (id) {
+ extra = extra | ID;
+ setChunkIndex(fNodeExtra, extra, attrChunk, attrIndex);
+ String value = getChunkValue(fNodeValue, attrChunk, attrIndex);
+ putIdentifier(value, elementNodeIndex);
+ }
+ // store type information
+ if (type != null) {
+ int extraDataIndex = createNode(DeferredNode.TYPE_NODE);
+ int echunk = extraDataIndex >> CHUNK_SHIFT;
+ int eindex = extraDataIndex & CHUNK_MASK;
+
+ setChunkIndex(fNodeLastChild, extraDataIndex, attrChunk, attrIndex);
+ setChunkValue(fNodeValue, type, echunk, eindex);
+ }
+
+ // return node index
+ return attrNodeIndex;
+ }
+
+ /**
+ * Sets an attribute on an element node.
+ * @deprecated
+ */
+ public int setDeferredAttribute(int elementNodeIndex,
+ String attrName, String attrURI,
+ String attrValue, boolean specified) {
+ // create attribute
+ int attrNodeIndex = createDeferredAttribute(attrName, attrURI,
+ attrValue, specified);
+ int attrChunk = attrNodeIndex >> CHUNK_SHIFT;
+ int attrIndex = attrNodeIndex & CHUNK_MASK;
+ // set attribute's parent to element
+ setChunkIndex(fNodeParent, elementNodeIndex, attrChunk, attrIndex);
+
+ int elementChunk = elementNodeIndex >> CHUNK_SHIFT;
+ int elementIndex = elementNodeIndex & CHUNK_MASK;
+
+ // get element's last attribute
+ int lastAttrNodeIndex = getChunkIndex(fNodeExtra,
+ elementChunk, elementIndex);
+ if (lastAttrNodeIndex != 0) {
+ // add link from new attribute to last attribute
+ setChunkIndex(fNodePrevSib, lastAttrNodeIndex,
+ attrChunk, attrIndex);
+ }
+ // add link from element to new last attribute
+ setChunkIndex(fNodeExtra, attrNodeIndex,
+ elementChunk, elementIndex);
+
+ // return node index
+ return attrNodeIndex;
+
+ } // setDeferredAttribute(int,String,String,String,boolean):int
+
+ /** Creates an attribute in the table. */
+ public int createDeferredAttribute(String attrName, String attrValue,
+ boolean specified) {
+ return createDeferredAttribute(attrName, null, attrValue, specified);
+ }
+
+ /** Creates an attribute with a URI in the table. */
+ public int createDeferredAttribute(String attrName, String attrURI,
+ String attrValue, boolean specified) {
+
+ // create node
+ int nodeIndex = createNode(NodeImpl.ATTRIBUTE_NODE);
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ setChunkValue(fNodeName, attrName, chunk, index);
+ setChunkValue(fNodeURI, attrURI, chunk, index);
+ setChunkValue(fNodeValue, attrValue, chunk, index);
+ int extra = specified ? SPECIFIED : 0;
+ setChunkIndex(fNodeExtra, extra, chunk, index);
+
+ // return node index
+ return nodeIndex;
+
+ } // createDeferredAttribute(String,String,String,boolean):int
+
+ /** Creates an element definition in the table.*/
+ public int createDeferredElementDefinition(String elementName) {
+
+ // create node
+ int nodeIndex = createNode(NodeImpl.ELEMENT_DEFINITION_NODE);
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ setChunkValue(fNodeName, elementName, chunk, index);
+
+ // return node index
+ return nodeIndex;
+
+ } // createDeferredElementDefinition(String):int
+
+ /** Creates a text node in the table. */
+ public int createDeferredTextNode(String data,
+ boolean ignorableWhitespace) {
+
+ // create node
+ int nodeIndex = createNode(Node.TEXT_NODE);
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ setChunkValue(fNodeValue, data, chunk, index);
+ // use extra to store ignorableWhitespace info
+ setChunkIndex(fNodeExtra, ignorableWhitespace ? 1 : 0, chunk, index);
+
+ // return node index
+ return nodeIndex;
+
+ } // createDeferredTextNode(String,boolean):int
+
+ /** Creates a CDATA section node in the table. */
+ public int createDeferredCDATASection(String data) {
+
+ // create node
+ int nodeIndex = createNode(Node.CDATA_SECTION_NODE);
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ setChunkValue(fNodeValue, data, chunk, index);
+
+ // return node index
+ return nodeIndex;
+
+ } // createDeferredCDATASection(String):int
+
+ /** Creates a processing instruction node in the table. */
+ public int createDeferredProcessingInstruction(String target,
+ String data) {
+ // create node
+ int nodeIndex = createNode(Node.PROCESSING_INSTRUCTION_NODE);
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ setChunkValue(fNodeName, target, chunk, index);
+ setChunkValue(fNodeValue, data, chunk, index);
+ // return node index
+ return nodeIndex;
+
+ } // createDeferredProcessingInstruction(String,String):int
+
+ /** Creates a comment node in the table. */
+ public int createDeferredComment(String data) {
+
+ // create node
+ int nodeIndex = createNode(Node.COMMENT_NODE);
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ setChunkValue(fNodeValue, data, chunk, index);
+
+ // return node index
+ return nodeIndex;
+
+ } // createDeferredComment(String):int
+
+ /** Creates a clone of the specified node. */
+ public int cloneNode(int nodeIndex, boolean deep) {
+
+ // clone immediate node
+
+ int nchunk = nodeIndex >> CHUNK_SHIFT;
+ int nindex = nodeIndex & CHUNK_MASK;
+ int nodeType = fNodeType[nchunk][nindex];
+ int cloneIndex = createNode((short)nodeType);
+ int cchunk = cloneIndex >> CHUNK_SHIFT;
+ int cindex = cloneIndex & CHUNK_MASK;
+ setChunkValue(fNodeName, fNodeName[nchunk][nindex], cchunk, cindex);
+ setChunkValue(fNodeValue, fNodeValue[nchunk][nindex], cchunk, cindex);
+ setChunkValue(fNodeURI, fNodeURI[nchunk][nindex], cchunk, cindex);
+ int extraIndex = fNodeExtra[nchunk][nindex];
+ if (extraIndex != -1) {
+ if (nodeType != Node.ATTRIBUTE_NODE && nodeType != Node.TEXT_NODE) {
+ extraIndex = cloneNode(extraIndex, false);
+ }
+ setChunkIndex(fNodeExtra, extraIndex, cchunk, cindex);
+ }
+
+ // clone and attach children
+ if (deep) {
+ int prevIndex = -1;
+ int childIndex = getLastChild(nodeIndex, false);
+ while (childIndex != -1) {
+ int clonedChildIndex = cloneNode(childIndex, deep);
+ insertBefore(cloneIndex, clonedChildIndex, prevIndex);
+ prevIndex = clonedChildIndex;
+ childIndex = getRealPrevSibling(childIndex, false);
+ }
+
+
+ }
+
+ // return cloned node index
+ return cloneIndex;
+
+ } // cloneNode(int,boolean):int
+
+ /** Appends a child to the specified parent in the table. */
+ public void appendChild(int parentIndex, int childIndex) {
+
+ // append parent index
+ int pchunk = parentIndex >> CHUNK_SHIFT;
+ int pindex = parentIndex & CHUNK_MASK;
+ int cchunk = childIndex >> CHUNK_SHIFT;
+ int cindex = childIndex & CHUNK_MASK;
+ setChunkIndex(fNodeParent, parentIndex, cchunk, cindex);
+
+ // set previous sibling of new child
+ int olast = getChunkIndex(fNodeLastChild, pchunk, pindex);
+ setChunkIndex(fNodePrevSib, olast, cchunk, cindex);
+
+ // update parent's last child
+ setChunkIndex(fNodeLastChild, childIndex, pchunk, pindex);
+
+ } // appendChild(int,int)
+
+ /** Adds an attribute node to the specified element. */
+ public int setAttributeNode(int elemIndex, int attrIndex) {
+
+ int echunk = elemIndex >> CHUNK_SHIFT;
+ int eindex = elemIndex & CHUNK_MASK;
+ int achunk = attrIndex >> CHUNK_SHIFT;
+ int aindex = attrIndex & CHUNK_MASK;
+
+ // see if this attribute is already here
+ String attrName = getChunkValue(fNodeName, achunk, aindex);
+ int oldAttrIndex = getChunkIndex(fNodeExtra, echunk, eindex);
+ int nextIndex = -1;
+ int oachunk = -1;
+ int oaindex = -1;
+ while (oldAttrIndex != -1) {
+ oachunk = oldAttrIndex >> CHUNK_SHIFT;
+ oaindex = oldAttrIndex & CHUNK_MASK;
+ String oldAttrName = getChunkValue(fNodeName, oachunk, oaindex);
+ if (oldAttrName.equals(attrName)) {
+ break;
+ }
+ nextIndex = oldAttrIndex;
+ oldAttrIndex = getChunkIndex(fNodePrevSib, oachunk, oaindex);
+ }
+
+ // remove old attribute
+ if (oldAttrIndex != -1) {
+
+ // patch links
+ int prevIndex = getChunkIndex(fNodePrevSib, oachunk, oaindex);
+ if (nextIndex == -1) {
+ setChunkIndex(fNodeExtra, prevIndex, echunk, eindex);
+ }
+ else {
+ int pchunk = nextIndex >> CHUNK_SHIFT;
+ int pindex = nextIndex & CHUNK_MASK;
+ setChunkIndex(fNodePrevSib, prevIndex, pchunk, pindex);
+ }
+
+ // remove connections to siblings
+ clearChunkIndex(fNodeType, oachunk, oaindex);
+ clearChunkValue(fNodeName, oachunk, oaindex);
+ clearChunkValue(fNodeValue, oachunk, oaindex);
+ clearChunkIndex(fNodeParent, oachunk, oaindex);
+ clearChunkIndex(fNodePrevSib, oachunk, oaindex);
+ int attrTextIndex =
+ clearChunkIndex(fNodeLastChild, oachunk, oaindex);
+ int atchunk = attrTextIndex >> CHUNK_SHIFT;
+ int atindex = attrTextIndex & CHUNK_MASK;
+ clearChunkIndex(fNodeType, atchunk, atindex);
+ clearChunkValue(fNodeValue, atchunk, atindex);
+ clearChunkIndex(fNodeParent, atchunk, atindex);
+ clearChunkIndex(fNodeLastChild, atchunk, atindex);
+ }
+
+ // add new attribute
+ int prevIndex = getChunkIndex(fNodeExtra, echunk, eindex);
+ setChunkIndex(fNodeExtra, attrIndex, echunk, eindex);
+ setChunkIndex(fNodePrevSib, prevIndex, achunk, aindex);
+
+ // return
+ return oldAttrIndex;
+
+ } // setAttributeNode(int,int):int
+
+
+ /** Adds an attribute node to the specified element. */
+ public void setIdAttributeNode(int elemIndex, int attrIndex) {
+
+ int chunk = attrIndex >> CHUNK_SHIFT;
+ int index = attrIndex & CHUNK_MASK;
+ int extra = getChunkIndex(fNodeExtra, chunk, index);
+ extra = extra | ID;
+ setChunkIndex(fNodeExtra, extra, chunk, index);
+
+ String value = getChunkValue(fNodeValue, chunk, index);
+ putIdentifier(value, elemIndex);
+ }
+
+
+ /** Sets type of attribute */
+ public void setIdAttribute(int attrIndex) {
+
+ int chunk = attrIndex >> CHUNK_SHIFT;
+ int index = attrIndex & CHUNK_MASK;
+ int extra = getChunkIndex(fNodeExtra, chunk, index);
+ extra = extra | ID;
+ setChunkIndex(fNodeExtra, extra, chunk, index);
+ }
+
+ /** Inserts a child before the specified node in the table. */
+ public int insertBefore(int parentIndex, int newChildIndex, int refChildIndex) {
+
+ if (refChildIndex == -1) {
+ appendChild(parentIndex, newChildIndex);
+ return newChildIndex;
+ }
+
+ int nchunk = newChildIndex >> CHUNK_SHIFT;
+ int nindex = newChildIndex & CHUNK_MASK;
+ int rchunk = refChildIndex >> CHUNK_SHIFT;
+ int rindex = refChildIndex & CHUNK_MASK;
+ int previousIndex = getChunkIndex(fNodePrevSib, rchunk, rindex);
+ setChunkIndex(fNodePrevSib, newChildIndex, rchunk, rindex);
+ setChunkIndex(fNodePrevSib, previousIndex, nchunk, nindex);
+
+ return newChildIndex;
+
+ } // insertBefore(int,int,int):int
+
+ /** Sets the last child of the parentIndex to childIndex. */
+ public void setAsLastChild(int parentIndex, int childIndex) {
+ int pchunk = parentIndex >> CHUNK_SHIFT;
+ int pindex = parentIndex & CHUNK_MASK;
+ setChunkIndex(fNodeLastChild, childIndex, pchunk, pindex);
+ } // setAsLastChild(int,int)
+
+ /**
+ * Returns the parent node of the given node.
+ * Calling this method does not free the parent index.
+ */
+ public int getParentNode(int nodeIndex) {
+ return getParentNode(nodeIndex, false);
+ }
+
+ /**
+ * Returns the parent node of the given node.
+ * @param free True to free parent node.
+ */
+ public int getParentNode(int nodeIndex, boolean free) {
+
+ if (nodeIndex == -1) {
+ return -1;
+ }
+
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ return free ? clearChunkIndex(fNodeParent, chunk, index)
+ : getChunkIndex(fNodeParent, chunk, index);
+
+ } // getParentNode(int):int
+
+ /** Returns the last child of the given node. */
+ public int getLastChild(int nodeIndex) {
+ return getLastChild(nodeIndex, true);
+ }
+
+ /**
+ * Returns the last child of the given node.
+ * @param free True to free child index.
+ */
+ public int getLastChild(int nodeIndex, boolean free) {
+
+ if (nodeIndex == -1) {
+ return -1;
+ }
+
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ return free ? clearChunkIndex(fNodeLastChild, chunk, index)
+ : getChunkIndex(fNodeLastChild, chunk, index);
+
+ } // getLastChild(int,boolean):int
+
+ /**
+ * Returns the prev sibling of the given node.
+ * This is post-normalization of Text Nodes.
+ */
+ public int getPrevSibling(int nodeIndex) {
+ return getPrevSibling(nodeIndex, true);
+ }
+
+ /**
+ * Returns the prev sibling of the given node.
+ * @param free True to free sibling index.
+ */
+ public int getPrevSibling(int nodeIndex, boolean free) {
+
+ if (nodeIndex == -1) {
+ return -1;
+ }
+
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ int type = getChunkIndex(fNodeType, chunk, index);
+ if (type == Node.TEXT_NODE) {
+ do {
+ nodeIndex = getChunkIndex(fNodePrevSib, chunk, index);
+ if (nodeIndex == -1) {
+ break;
+ }
+ chunk = nodeIndex >> CHUNK_SHIFT;
+ index = nodeIndex & CHUNK_MASK;
+ type = getChunkIndex(fNodeType, chunk, index);
+ } while (type == Node.TEXT_NODE);
+ }
+ else {
+ nodeIndex = getChunkIndex(fNodePrevSib, chunk, index);
+ }
+
+ return nodeIndex;
+
+ } // getPrevSibling(int,boolean):int
+
+ /**
+ * Returns the real prev sibling of the given node,
+ * directly from the data structures. Used by TextImpl#getNodeValue()
+ * to normalize values.
+ */
+ public int getRealPrevSibling(int nodeIndex) {
+ return getRealPrevSibling(nodeIndex, true);
+ }
+
+ /**
+ * Returns the real prev sibling of the given node.
+ * @param free True to free sibling index.
+ */
+ public int getRealPrevSibling(int nodeIndex, boolean free) {
+
+ if (nodeIndex == -1) {
+ return -1;
+ }
+
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ return free ? clearChunkIndex(fNodePrevSib, chunk, index)
+ : getChunkIndex(fNodePrevSib, chunk, index);
+
+ } // getReadPrevSibling(int,boolean):int
+
+ /**
+ * Returns the index of the element definition in the table
+ * with the specified name index, or -1 if no such definition
+ * exists.
+ */
+ public int lookupElementDefinition(String elementName) {
+
+ if (fNodeCount > 1) {
+
+ // find doctype
+ int docTypeIndex = -1;
+ int nchunk = 0;
+ int nindex = 0;
+ for (int index = getChunkIndex(fNodeLastChild, nchunk, nindex);
+ index != -1;
+ index = getChunkIndex(fNodePrevSib, nchunk, nindex)) {
+
+ nchunk = index >> CHUNK_SHIFT;
+ nindex = index & CHUNK_MASK;
+ if (getChunkIndex(fNodeType, nchunk, nindex) == Node.DOCUMENT_TYPE_NODE) {
+ docTypeIndex = index;
+ break;
+ }
+ }
+
+ // find element definition
+ if (docTypeIndex == -1) {
+ return -1;
+ }
+ nchunk = docTypeIndex >> CHUNK_SHIFT;
+ nindex = docTypeIndex & CHUNK_MASK;
+ for (int index = getChunkIndex(fNodeLastChild, nchunk, nindex);
+ index != -1;
+ index = getChunkIndex(fNodePrevSib, nchunk, nindex)) {
+
+ nchunk = index >> CHUNK_SHIFT;
+ nindex = index & CHUNK_MASK;
+ if (getChunkIndex(fNodeType, nchunk, nindex) ==
+ NodeImpl.ELEMENT_DEFINITION_NODE
+ && getChunkValue(fNodeName, nchunk, nindex) == elementName) {
+ return index;
+ }
+ }
+ }
+
+ return -1;
+
+ } // lookupElementDefinition(String):int
+
+ /** Instantiates the requested node object. */
+ public DeferredNode getNodeObject(int nodeIndex) {
+
+ // is there anything to do?
+ if (nodeIndex == -1) {
+ return null;
+ }
+
+ // get node type
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ int type = getChunkIndex(fNodeType, chunk, index);
+ if (type != Node.TEXT_NODE && type != Node.CDATA_SECTION_NODE) {
+ clearChunkIndex(fNodeType, chunk, index);
+ }
+
+ // create new node
+ DeferredNode node = null;
+ switch (type) {
+
+ //
+ // Standard DOM node types
+ //
+
+ case Node.ATTRIBUTE_NODE: {
+ if (fNamespacesEnabled) {
+ node = new DeferredAttrNSImpl(this, nodeIndex);
+ } else {
+ node = new DeferredAttrImpl(this, nodeIndex);
+ }
+ break;
+ }
+
+ case Node.CDATA_SECTION_NODE: {
+ node = new DeferredCDATASectionImpl(this, nodeIndex);
+ break;
+ }
+
+ case Node.COMMENT_NODE: {
+ node = new DeferredCommentImpl(this, nodeIndex);
+ break;
+ }
+
+ // NOTE: Document fragments can never be "fast".
+ //
+ // The parser will never ask to create a document
+ // fragment during the parse. Document fragments
+ // are used by the application *after* the parse.
+ //
+ // case Node.DOCUMENT_FRAGMENT_NODE: { break; }
+ case Node.DOCUMENT_NODE: {
+ // this node is never "fast"
+ node = this;
+ break;
+ }
+
+ case Node.DOCUMENT_TYPE_NODE: {
+ node = new DeferredDocumentTypeImpl(this, nodeIndex);
+ // save the doctype node
+ docType = (DocumentTypeImpl)node;
+ break;
+ }
+
+ case Node.ELEMENT_NODE: {
+
+ if (DEBUG_IDS) {
+ System.out.println("getNodeObject(ELEMENT_NODE): "+nodeIndex);
+ }
+
+ // create node
+ if (fNamespacesEnabled) {
+ node = new DeferredElementNSImpl(this, nodeIndex);
+ } else {
+ node = new DeferredElementImpl(this, nodeIndex);
+ }
+
+ // check to see if this element needs to be
+ // registered for its ID attributes
+ if (fIdElement != null) {
+ int idIndex = binarySearch(fIdElement, 0,
+ fIdCount-1, nodeIndex);
+ while (idIndex != -1) {
+
+ if (DEBUG_IDS) {
+ System.out.println(" id index: "+idIndex);
+ System.out.println(" fIdName["+idIndex+
+ "]: "+fIdName[idIndex]);
+ }
+
+ // register ID
+ String name = fIdName[idIndex];
+ if (name != null) {
+ if (DEBUG_IDS) {
+ System.out.println(" name: "+name);
+ System.out.print("getNodeObject()#");
+ }
+ putIdentifier0(name, (Element)node);
+ fIdName[idIndex] = null;
+ }
+
+ // continue if there are more IDs for
+ // this element
+ if (idIndex + 1 < fIdCount &&
+ fIdElement[idIndex + 1] == nodeIndex) {
+ idIndex++;
+ }
+ else {
+ idIndex = -1;
+ }
+ }
+ }
+ break;
+ }
+
+ case Node.ENTITY_NODE: {
+ node = new DeferredEntityImpl(this, nodeIndex);
+ break;
+ }
+
+ case Node.ENTITY_REFERENCE_NODE: {
+ node = new DeferredEntityReferenceImpl(this, nodeIndex);
+ break;
+ }
+
+ case Node.NOTATION_NODE: {
+ node = new DeferredNotationImpl(this, nodeIndex);
+ break;
+ }
+
+ case Node.PROCESSING_INSTRUCTION_NODE: {
+ node = new DeferredProcessingInstructionImpl(this, nodeIndex);
+ break;
+ }
+
+ case Node.TEXT_NODE: {
+ node = new DeferredTextImpl(this, nodeIndex);
+ break;
+ }
+
+ //
+ // non-standard DOM node types
+ //
+
+ case NodeImpl.ELEMENT_DEFINITION_NODE: {
+ node = new DeferredElementDefinitionImpl(this, nodeIndex);
+ break;
+ }
+
+ default: {
+ throw new IllegalArgumentException("type: "+type);
+ }
+
+ } // switch node type
+
+ // store and return
+ if (node != null) {
+ return node;
+ }
+
+ // error
+ throw new IllegalArgumentException();
+
+ } // createNodeObject(int):Node
+
+ /** Returns the name of the given node. */
+ public String getNodeName(int nodeIndex) {
+ return getNodeName(nodeIndex, true);
+ } // getNodeNameString(int):String
+
+ /**
+ * Returns the name of the given node.
+ * @param free True to free the string index.
+ */
+ public String getNodeName(int nodeIndex, boolean free) {
+
+ if (nodeIndex == -1) {
+ return null;
+ }
+
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ return free ? clearChunkValue(fNodeName, chunk, index)
+ : getChunkValue(fNodeName, chunk, index);
+
+ } // getNodeName(int,boolean):String
+
+ /** Returns the real value of the given node. */
+ public String getNodeValueString(int nodeIndex) {
+ return getNodeValueString(nodeIndex, true);
+ } // getNodeValueString(int):String
+
+ /**
+ * Returns the real value of the given node.
+ * @param free True to free the string index.
+ */
+ public String getNodeValueString(int nodeIndex, boolean free) {
+
+ if (nodeIndex == -1) {
+ return null;
+ }
+
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ String value = free ? clearChunkValue(fNodeValue, chunk, index)
+ : getChunkValue(fNodeValue, chunk, index);
+ if (value == null) {
+ return null;
+ }
+
+ int type = getChunkIndex(fNodeType, chunk, index);
+ if (type == Node.TEXT_NODE) {
+ int prevSib = getRealPrevSibling(nodeIndex);
+ if (prevSib != -1 &&
+ getNodeType(prevSib, false) == Node.TEXT_NODE) {
+ // append data that is stored in fNodeValue
+ // REVISIT: for text nodes it works differently than for CDATA
+ // nodes.
+ fStrChunks.add(value);
+ do {
+ // go in reverse order: find last child, then
+ // its previous sibling, etc
+ chunk = prevSib >> CHUNK_SHIFT;
+ index = prevSib & CHUNK_MASK;
+ value = getChunkValue(fNodeValue, chunk, index);
+ fStrChunks.add(value);
+ prevSib = getChunkIndex(fNodePrevSib, chunk, index);
+ if (prevSib == -1) {
+ break;
+ }
+ } while (getNodeType(prevSib, false) == Node.TEXT_NODE);
+
+ int chunkCount = fStrChunks.size();
+
+ // add to the buffer in the correct order.
+ for (int i = chunkCount - 1; i >= 0; i--) {
+ fBufferStr.append((String)fStrChunks.get(i));
+ }
+
+ value = fBufferStr.toString();
+ fStrChunks.clear();
+ fBufferStr.setLength(0);
+ return value;
+ }
+ }
+ else if (type == Node.CDATA_SECTION_NODE) {
+ // find if any other data stored in children
+ int child = getLastChild(nodeIndex, false);
+ if (child !=-1) {
+ // append data that is stored in fNodeValue
+ fBufferStr.append(value);
+ while (child !=-1) {
+ // go in reverse order: find last child, then
+ // its previous sibling, etc
+ chunk = child >> CHUNK_SHIFT;
+ index = child & CHUNK_MASK;
+ value = getChunkValue(fNodeValue, chunk, index);
+ fStrChunks.add(value);
+ child = getChunkIndex(fNodePrevSib, chunk, index);
+ }
+ // add to the buffer in the correct order.
+ for (int i=fStrChunks.size()-1; i>=0; i--) {
+ fBufferStr.append((String)fStrChunks.get(i));
+ }
+
+ value = fBufferStr.toString();
+ fStrChunks.clear();
+ fBufferStr.setLength(0);
+ return value;
+ }
+ }
+
+ return value;
+
+ } // getNodeValueString(int,boolean):String
+
+ /**
+ * Returns the value of the given node.
+ */
+ public String getNodeValue(int nodeIndex) {
+ return getNodeValue(nodeIndex, true);
+ }
+
+ /**
+ * Clears the type info that is stored in the fNodeValue array
+ * @param nodeIndex
+ * @return Object - type information for the attribute/element node
+ */
+ public Object getTypeInfo(int nodeIndex) {
+ if (nodeIndex == -1) {
+ return null;
+ }
+
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+
+
+ Object value = fNodeValue[chunk] != null ? fNodeValue[chunk][index] : null;
+ if (value != null) {
+ fNodeValue[chunk][index] = null;
+ RefCount c = (RefCount) fNodeValue[chunk][CHUNK_SIZE];
+ c.fCount--;
+ if (c.fCount == 0) {
+ fNodeValue[chunk] = null;
+ }
+ }
+ return value;
+ }
+
+ /**
+ * Returns the value of the given node.
+ * @param free True to free the value index.
+ */
+ public String getNodeValue(int nodeIndex, boolean free) {
+
+ if (nodeIndex == -1) {
+ return null;
+ }
+
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ return free ? clearChunkValue(fNodeValue, chunk, index)
+ : getChunkValue(fNodeValue, chunk, index);
+
+ } // getNodeValue(int,boolean):String
+
+ /**
+ * Returns the extra info of the given node.
+ * Used by AttrImpl to store specified value (1 == true).
+ */
+ public int getNodeExtra(int nodeIndex) {
+ return getNodeExtra(nodeIndex, true);
+ }
+
+ /**
+ * Returns the extra info of the given node.
+ * @param free True to free the value index.
+ */
+ public int getNodeExtra(int nodeIndex, boolean free) {
+
+ if (nodeIndex == -1) {
+ return -1;
+ }
+
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ return free ? clearChunkIndex(fNodeExtra, chunk, index)
+ : getChunkIndex(fNodeExtra, chunk, index);
+
+ } // getNodeExtra(int,boolean):int
+
+ /** Returns the type of the given node. */
+ public short getNodeType(int nodeIndex) {
+ return getNodeType(nodeIndex, true);
+ }
+
+ /**
+ * Returns the type of the given node.
+ * @param free True to free type index.
+ */
+ public short getNodeType(int nodeIndex, boolean free) {
+
+ if (nodeIndex == -1) {
+ return -1;
+ }
+
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ return free ? (short)clearChunkIndex(fNodeType, chunk, index)
+ : (short)getChunkIndex(fNodeType, chunk, index);
+
+ } // getNodeType(int):int
+
+ /** Returns the attribute value of the given name. */
+ public String getAttribute(int elemIndex, String name) {
+ if (elemIndex == -1 || name == null) {
+ return null;
+ }
+ int echunk = elemIndex >> CHUNK_SHIFT;
+ int eindex = elemIndex & CHUNK_MASK;
+ int attrIndex = getChunkIndex(fNodeExtra, echunk, eindex);
+ while (attrIndex != -1) {
+ int achunk = attrIndex >> CHUNK_SHIFT;
+ int aindex = attrIndex & CHUNK_MASK;
+ if (getChunkValue(fNodeName, achunk, aindex) == name) {
+ return getChunkValue(fNodeValue, achunk, aindex);
+ }
+ attrIndex = getChunkIndex(fNodePrevSib, achunk, aindex);
+ }
+ return null;
+ }
+
+ /** Returns the URI of the given node. */
+ public String getNodeURI(int nodeIndex) {
+ return getNodeURI(nodeIndex, true);
+ }
+
+ /**
+ * Returns the URI of the given node.
+ * @param free True to free URI index.
+ */
+ public String getNodeURI(int nodeIndex, boolean free) {
+
+ if (nodeIndex == -1) {
+ return null;
+ }
+
+ int chunk = nodeIndex >> CHUNK_SHIFT;
+ int index = nodeIndex & CHUNK_MASK;
+ return free ? clearChunkValue(fNodeURI, chunk, index)
+ : getChunkValue(fNodeURI, chunk, index);
+
+ } // getNodeURI(int,int):String
+
+ // identifier maintenance
+
+ /** Registers an identifier name with a specified element node. */
+ public void putIdentifier(String name, int elementNodeIndex) {
+
+ if (DEBUG_IDS) {
+ System.out.println("putIdentifier(" + name + ", "
+ + elementNodeIndex + ')' + " // " +
+ getChunkValue(fNodeName,
+ elementNodeIndex >> CHUNK_SHIFT,
+ elementNodeIndex & CHUNK_MASK));
+ }
+
+ // initialize arrays
+ if (fIdName == null) {
+ fIdName = new String[64];
+ fIdElement = new int[64];
+ }
+
+ // resize arrays
+ if (fIdCount == fIdName.length) {
+ String idName[] = new String[fIdCount * 2];
+ System.arraycopy(fIdName, 0, idName, 0, fIdCount);
+ fIdName = idName;
+
+ int idElement[] = new int[idName.length];
+ System.arraycopy(fIdElement, 0, idElement, 0, fIdCount);
+ fIdElement = idElement;
+ }
+
+ // store identifier
+ fIdName[fIdCount] = name;
+ fIdElement[fIdCount] = elementNodeIndex;
+ fIdCount++;
+
+ } // putIdentifier(String,int)
+
+ //
+ // DEBUG
+ //
+
+ /** Prints out the tables. */
+ public void print() {
+
+ if (DEBUG_PRINT_REF_COUNTS) {
+ System.out.print("num\t");
+ System.out.print("type\t");
+ System.out.print("name\t");
+ System.out.print("val\t");
+ System.out.print("par\t");
+ System.out.print("lch\t");
+ System.out.print("psib");
+ System.out.println();
+ for (int i = 0; i < fNodeType.length; i++) {
+ if (fNodeType[i] != null) {
+ // separator
+ System.out.print("--------");
+ System.out.print("--------");
+ System.out.print("--------");
+ System.out.print("--------");
+ System.out.print("--------");
+ System.out.print("--------");
+ System.out.print("--------");
+ System.out.println();
+
+ // ref count
+ System.out.print(i);
+ System.out.print('\t');
+ switch (fNodeType[i][CHUNK_SIZE]) {
+ case DocumentImpl.ELEMENT_DEFINITION_NODE: { System.out.print("EDef"); break; }
+ case Node.DOCUMENT_NODE: { System.out.print("Doc"); break; }
+ case Node.DOCUMENT_TYPE_NODE: { System.out.print("DType"); break; }
+ case Node.COMMENT_NODE: { System.out.print("Com"); break; }
+ case Node.PROCESSING_INSTRUCTION_NODE: { System.out.print("PI"); break; }
+ case Node.ELEMENT_NODE: { System.out.print("Elem"); break; }
+ case Node.ENTITY_NODE: { System.out.print("Ent"); break; }
+ case Node.ENTITY_REFERENCE_NODE: { System.out.print("ERef"); break; }
+ case Node.TEXT_NODE: { System.out.print("Text"); break; }
+ case Node.ATTRIBUTE_NODE: { System.out.print("Attr"); break; }
+ case DeferredNode.TYPE_NODE: { System.out.print("TypeInfo"); break; }
+ default: { System.out.print("?"+fNodeType[i][CHUNK_SIZE]); }
+ }
+ System.out.print('\t');
+ System.out.print(fNodeName[i][CHUNK_SIZE]);
+ System.out.print('\t');
+ System.out.print(fNodeValue[i][CHUNK_SIZE]);
+ System.out.print('\t');
+ System.out.print(fNodeURI[i][CHUNK_SIZE]);
+ System.out.print('\t');
+ System.out.print(fNodeParent[i][CHUNK_SIZE]);
+ System.out.print('\t');
+ System.out.print(fNodeLastChild[i][CHUNK_SIZE]);
+ System.out.print('\t');
+ System.out.print(fNodePrevSib[i][CHUNK_SIZE]);
+ System.out.print('\t');
+ System.out.print(fNodeExtra[i][CHUNK_SIZE]);
+ System.out.println();
+ }
+ }
+ }
+
+ if (DEBUG_PRINT_TABLES) {
+ // This assumes that the document is small
+ System.out.println("# start table");
+ for (int i = 0; i < fNodeCount; i++) {
+ int chunk = i >> CHUNK_SHIFT;
+ int index = i & CHUNK_MASK;
+ if (i % 10 == 0) {
+ System.out.print("num\t");
+ System.out.print("type\t");
+ System.out.print("name\t");
+ System.out.print("val\t");
+ System.out.print("uri\t");
+ System.out.print("par\t");
+ System.out.print("lch\t");
+ System.out.print("psib\t");
+ System.out.print("xtra");
+ System.out.println();
+ }
+ System.out.print(i);
+ System.out.print('\t');
+ switch (getChunkIndex(fNodeType, chunk, index)) {
+ case DocumentImpl.ELEMENT_DEFINITION_NODE: { System.out.print("EDef"); break; }
+ case Node.DOCUMENT_NODE: { System.out.print("Doc"); break; }
+ case Node.DOCUMENT_TYPE_NODE: { System.out.print("DType"); break; }
+ case Node.COMMENT_NODE: { System.out.print("Com"); break; }
+ case Node.PROCESSING_INSTRUCTION_NODE: { System.out.print("PI"); break; }
+ case Node.ELEMENT_NODE: { System.out.print("Elem"); break; }
+ case Node.ENTITY_NODE: { System.out.print("Ent"); break; }
+ case Node.ENTITY_REFERENCE_NODE: { System.out.print("ERef"); break; }
+ case Node.TEXT_NODE: { System.out.print("Text"); break; }
+ case Node.ATTRIBUTE_NODE: { System.out.print("Attr"); break; }
+ case DeferredNode.TYPE_NODE: { System.out.print("TypeInfo"); break; }
+ default: { System.out.print("?"+getChunkIndex(fNodeType, chunk, index)); }
+ }
+ System.out.print('\t');
+ System.out.print(getChunkValue(fNodeName, chunk, index));
+ System.out.print('\t');
+ System.out.print(getNodeValue(chunk, index));
+ System.out.print('\t');
+ System.out.print(getChunkValue(fNodeURI, chunk, index));
+ System.out.print('\t');
+ System.out.print(getChunkIndex(fNodeParent, chunk, index));
+ System.out.print('\t');
+ System.out.print(getChunkIndex(fNodeLastChild, chunk, index));
+ System.out.print('\t');
+ System.out.print(getChunkIndex(fNodePrevSib, chunk, index));
+ System.out.print('\t');
+ System.out.print(getChunkIndex(fNodeExtra, chunk, index));
+ System.out.println();
+ }
+ System.out.println("# end table");
+ }
+
+ } // print()
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex() {
+ return 0;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /** Synchronizes the node's data. */
+ protected void synchronizeData() {
+
+ // no need to sync in the future
+ needsSyncData(false);
+
+ // fluff up enough nodes to fill identifiers hash
+ if (fIdElement != null) {
+
+ // REVISIT: There has to be a more efficient way of
+ // doing this. But keep in mind that the
+ // tree can have been altered and re-ordered
+ // before all of the element nodes with ID
+ // attributes have been registered. For now
+ // this is reasonable and safe. -Ac
+
+ IntVector path = new IntVector();
+ for (int i = 0; i < fIdCount; i++) {
+
+ // ignore if it's already been registered
+ int elementNodeIndex = fIdElement[i];
+ String idName = fIdName[i];
+ if (idName == null) {
+ continue;
+ }
+
+ // find path from this element to the root
+ path.removeAllElements();
+ int index = elementNodeIndex;
+ do {
+ path.addElement(index);
+ int pchunk = index >> CHUNK_SHIFT;
+ int pindex = index & CHUNK_MASK;
+ index = getChunkIndex(fNodeParent, pchunk, pindex);
+ } while (index != -1);
+
+ // Traverse path (backwards), fluffing the elements
+ // along the way. When this loop finishes, "place"
+ // will contain the reference to the element node
+ // we're interested in. -Ac
+ Node place = this;
+ for (int j = path.size() - 2; j >= 0; j--) {
+ index = path.elementAt(j);
+ Node child = place.getLastChild();
+ while (child != null) {
+ if (child instanceof DeferredNode) {
+ int nodeIndex =
+ ((DeferredNode)child).getNodeIndex();
+ if (nodeIndex == index) {
+ place = child;
+ break;
+ }
+ }
+ child = child.getPreviousSibling();
+ }
+ }
+
+ // register the element
+ Element element = (Element)place;
+ putIdentifier0(idName, element);
+ fIdName[i] = null;
+
+ // see if there are more IDs on this element
+ while (i + 1 < fIdCount &&
+ fIdElement[i + 1] == elementNodeIndex) {
+ idName = fIdName[++i];
+ if (idName == null) {
+ continue;
+ }
+ putIdentifier0(idName, element);
+ }
+ }
+
+ } // if identifiers
+
+ } // synchronizeData()
+
+ /**
+ * Synchronizes the node's children with the internal structure.
+ * Fluffing the children at once solves a lot of work to keep
+ * the two structures in sync. The problem gets worse when
+ * editing the tree -- this makes it a lot easier.
+ */
+ protected void synchronizeChildren() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ /*
+ * when we have elements with IDs this method is being recursively
+ * called from synchronizeData, in which case we've already gone
+ * through the following and we can now simply stop here.
+ */
+ if (!needsSyncChildren()) {
+ return;
+ }
+ }
+
+ // we don't want to generate any event for this so turn them off
+ boolean orig = mutationEvents;
+ mutationEvents = false;
+
+ // no need to sync in the future
+ needsSyncChildren(false);
+
+ getNodeType(0);
+
+ // create children and link them as siblings
+ ChildNode first = null;
+ ChildNode last = null;
+ for (int index = getLastChild(0);
+ index != -1;
+ index = getPrevSibling(index)) {
+
+ ChildNode node = (ChildNode)getNodeObject(index);
+ if (last == null) {
+ last = node;
+ }
+ else {
+ first.previousSibling = node;
+ }
+ node.ownerNode = this;
+ node.isOwned(true);
+ node.nextSibling = first;
+ first = node;
+
+ // save doctype and document type
+ int type = node.getNodeType();
+ if (type == Node.ELEMENT_NODE) {
+ docElement = (ElementImpl)node;
+ }
+ else if (type == Node.DOCUMENT_TYPE_NODE) {
+ docType = (DocumentTypeImpl)node;
+ }
+ }
+
+ if (first != null) {
+ firstChild = first;
+ first.isFirstChild(true);
+ lastChild(last);
+ }
+
+ // set mutation events flag back to its original value
+ mutationEvents = orig;
+
+ } // synchronizeChildren()
+
+ /**
+ * Synchronizes the node's children with the internal structure.
+ * Fluffing the children at once solves a lot of work to keep
+ * the two structures in sync. The problem gets worse when
+ * editing the tree -- this makes it a lot easier.
+ * This is not directly used in this class but this method is
+ * here so that it can be shared by all deferred subclasses of AttrImpl.
+ */
+ protected final void synchronizeChildren(AttrImpl a, int nodeIndex) {
+
+ // we don't want to generate any event for this so turn them off
+ boolean orig = getMutationEvents();
+ setMutationEvents(false);
+
+ // no need to sync in the future
+ a.needsSyncChildren(false);
+
+ // create children and link them as siblings or simply store the value
+ // as a String if all we have is one piece of text
+ int last = getLastChild(nodeIndex);
+ int prev = getPrevSibling(last);
+ if (prev == -1) {
+ a.value = getNodeValueString(nodeIndex);
+ a.hasStringValue(true);
+ }
+ else {
+ ChildNode firstNode = null;
+ ChildNode lastNode = null;
+ for (int index = last; index != -1;
+ index = getPrevSibling(index)) {
+
+ ChildNode node = (ChildNode) getNodeObject(index);
+ if (lastNode == null) {
+ lastNode = node;
+ }
+ else {
+ firstNode.previousSibling = node;
+ }
+ node.ownerNode = a;
+ node.isOwned(true);
+ node.nextSibling = firstNode;
+ firstNode = node;
+ }
+ if (lastNode != null) {
+ a.value = firstNode; // firstChild = firstNode
+ firstNode.isFirstChild(true);
+ a.lastChild(lastNode);
+ }
+ a.hasStringValue(false);
+ }
+
+ // set mutation events flag back to its original value
+ setMutationEvents(orig);
+
+ } // synchronizeChildren(AttrImpl,int):void
+
+
+ /**
+ * Synchronizes the node's children with the internal structure.
+ * Fluffing the children at once solves a lot of work to keep
+ * the two structures in sync. The problem gets worse when
+ * editing the tree -- this makes it a lot easier.
+ * This is not directly used in this class but this method is
+ * here so that it can be shared by all deferred subclasses of ParentNode.
+ */
+ protected final void synchronizeChildren(ParentNode p, int nodeIndex) {
+
+ // we don't want to generate any event for this so turn them off
+ boolean orig = getMutationEvents();
+ setMutationEvents(false);
+
+ // no need to sync in the future
+ p.needsSyncChildren(false);
+
+ // create children and link them as siblings
+ ChildNode firstNode = null;
+ ChildNode lastNode = null;
+ for (int index = getLastChild(nodeIndex);
+ index != -1;
+ index = getPrevSibling(index)) {
+
+ ChildNode node = (ChildNode) getNodeObject(index);
+ if (lastNode == null) {
+ lastNode = node;
+ }
+ else {
+ firstNode.previousSibling = node;
+ }
+ node.ownerNode = p;
+ node.isOwned(true);
+ node.nextSibling = firstNode;
+ firstNode = node;
+ }
+ if (lastNode != null) {
+ p.firstChild = firstNode;
+ firstNode.isFirstChild(true);
+ p.lastChild(lastNode);
+ }
+
+ // set mutation events flag back to its original value
+ setMutationEvents(orig);
+
+ } // synchronizeChildren(ParentNode,int):void
+
+ // utility methods
+
+ /** Ensures that the internal tables are large enough. */
+ protected void ensureCapacity(int chunk) {
+ if (fNodeType == null) {
+ // create buffers
+ fNodeType = new int[INITIAL_CHUNK_COUNT][];
+ fNodeName = new Object[INITIAL_CHUNK_COUNT][];
+ fNodeValue = new Object[INITIAL_CHUNK_COUNT][];
+ fNodeParent = new int[INITIAL_CHUNK_COUNT][];
+ fNodeLastChild = new int[INITIAL_CHUNK_COUNT][];
+ fNodePrevSib = new int[INITIAL_CHUNK_COUNT][];
+ fNodeURI = new Object[INITIAL_CHUNK_COUNT][];
+ fNodeExtra = new int[INITIAL_CHUNK_COUNT][];
+ }
+ else if (fNodeType.length <= chunk) {
+ // resize the tables
+ int newsize = chunk * 2;
+
+ int[][] newArray = new int[newsize][];
+ System.arraycopy(fNodeType, 0, newArray, 0, chunk);
+ fNodeType = newArray;
+
+ Object[][] newStrArray = new Object[newsize][];
+ System.arraycopy(fNodeName, 0, newStrArray, 0, chunk);
+ fNodeName = newStrArray;
+
+ newStrArray = new Object[newsize][];
+ System.arraycopy(fNodeValue, 0, newStrArray, 0, chunk);
+ fNodeValue = newStrArray;
+
+ newArray = new int[newsize][];
+ System.arraycopy(fNodeParent, 0, newArray, 0, chunk);
+ fNodeParent = newArray;
+
+ newArray = new int[newsize][];
+ System.arraycopy(fNodeLastChild, 0, newArray, 0, chunk);
+ fNodeLastChild = newArray;
+
+ newArray = new int[newsize][];
+ System.arraycopy(fNodePrevSib, 0, newArray, 0, chunk);
+ fNodePrevSib = newArray;
+
+ newStrArray = new Object[newsize][];
+ System.arraycopy(fNodeURI, 0, newStrArray, 0, chunk);
+ fNodeURI = newStrArray;
+
+ newArray = new int[newsize][];
+ System.arraycopy(fNodeExtra, 0, newArray, 0, chunk);
+ fNodeExtra = newArray;
+ }
+ else if (fNodeType[chunk] != null) {
+ // Done - there's sufficient capacity
+ return;
+ }
+
+ // create new chunks
+ createChunk(fNodeType, chunk);
+ createChunk(fNodeName, chunk);
+ createChunk(fNodeValue, chunk);
+ createChunk(fNodeParent, chunk);
+ createChunk(fNodeLastChild, chunk);
+ createChunk(fNodePrevSib, chunk);
+ createChunk(fNodeURI, chunk);
+ createChunk(fNodeExtra, chunk);
+
+ // Done
+ return;
+
+ } // ensureCapacity(int,int)
+
+ /** Creates a node of the specified type. */
+ protected int createNode(short nodeType) {
+ // ensure tables are large enough
+ int chunk = fNodeCount >> CHUNK_SHIFT;
+ int index = fNodeCount & CHUNK_MASK;
+ ensureCapacity(chunk);
+
+ // initialize node
+ setChunkIndex(fNodeType, nodeType, chunk, index);
+
+ // return node index number
+ return fNodeCount++;
+
+ } // createNode(short):int
+
+ /**
+ * Performs a binary search for a target value in an array of
+ * values. The array of values must be in ascending sorted order
+ * before calling this method and all array values must be
+ * non-negative.
+ *
+ * @param values The array of values to search.
+ * @param start The starting offset of the search.
+ * @param end The ending offset of the search.
+ * @param target The target value.
+ *
+ * @return This function will return the first occurrence
+ * of the target value, or -1 if the target value cannot
+ * be found.
+ */
+ protected static int binarySearch(final int values[],
+ int start, int end, int target) {
+
+ if (DEBUG_IDS) {
+ System.out.println("binarySearch(), target: "+target);
+ }
+
+ // look for target value
+ while (start <= end) {
+
+ // is this the one we're looking for?
+ int middle = (start + end) >>> 1;
+ int value = values[middle];
+ if (DEBUG_IDS) {
+ System.out.print(" value: "+value+", target: "+target+" // ");
+ print(values, start, end, middle, target);
+ }
+ if (value == target) {
+ while (middle > 0 && values[middle - 1] == target) {
+ middle--;
+ }
+ if (DEBUG_IDS) {
+ System.out.println("FOUND AT "+middle);
+ }
+ return middle;
+ }
+
+ // is this point higher or lower?
+ if (value > target) {
+ end = middle - 1;
+ }
+ else {
+ start = middle + 1;
+ }
+
+ } // while
+
+ // not found
+ if (DEBUG_IDS) {
+ System.out.println("NOT FOUND!");
+ }
+ return -1;
+
+ } // binarySearch(int[],int,int,int):int
+
+ //
+ // Private methods
+ //
+ private static final int[] INIT_ARRAY = new int[CHUNK_SIZE + 1];
+ static {
+ for (int i = 0; i < CHUNK_SIZE; i++) {
+ INIT_ARRAY[i] = -1;
+ }
+ }
+ /** Creates the specified chunk in the given array of chunks. */
+ private final void createChunk(int data[][], int chunk) {
+ data[chunk] = new int[CHUNK_SIZE + 1];
+ System.arraycopy(INIT_ARRAY, 0, data[chunk], 0, CHUNK_SIZE);
+ }
+
+ static final class RefCount {
+ int fCount;
+ }
+
+ private final void createChunk(Object data[][], int chunk) {
+ data[chunk] = new Object[CHUNK_SIZE + 1];
+ data[chunk][CHUNK_SIZE] = new RefCount();
+ }
+
+ /**
+ * Sets the specified value in the given of data at the chunk and index.
+ *
+ * @return Returns the old value.
+ */
+ private final int setChunkIndex(int data[][], int value,
+ int chunk, int index) {
+ if (value == -1) {
+ return clearChunkIndex(data, chunk, index);
+ }
+ int [] dataChunk = data[chunk];
+ // Re-create chunk if it was deleted.
+ if (dataChunk == null) {
+ createChunk(data, chunk);
+ dataChunk = data[chunk];
+ }
+ int ovalue = dataChunk[index];
+ if (ovalue == -1) {
+ dataChunk[CHUNK_SIZE]++;
+ }
+ dataChunk[index] = value;
+ return ovalue;
+ }
+ private final String setChunkValue(Object data[][], Object value,
+ int chunk, int index) {
+ if (value == null) {
+ return clearChunkValue(data, chunk, index);
+ }
+ Object [] dataChunk = data[chunk];
+ // Re-create chunk if it was deleted.
+ if (dataChunk == null) {
+ createChunk(data, chunk);
+ dataChunk = data[chunk];
+ }
+ String ovalue = (String) dataChunk[index];
+ if (ovalue == null) {
+ RefCount c = (RefCount) dataChunk[CHUNK_SIZE];
+ c.fCount++;
+ }
+ dataChunk[index] = value;
+ return ovalue;
+ }
+
+ /**
+ * Returns the specified value in the given data at the chunk and index.
+ */
+ private final int getChunkIndex(int data[][], int chunk, int index) {
+ return data[chunk] != null ? data[chunk][index] : -1;
+ }
+ private final String getChunkValue(Object data[][], int chunk, int index) {
+ return data[chunk] != null ? (String) data[chunk][index] : null;
+ }
+ private final String getNodeValue(int chunk, int index) {
+ Object data = fNodeValue[chunk][index];
+ if (data == null){
+ return null;
+ }
+ else if (data instanceof String){
+ return (String)data;
+ }
+ else {
+ // type information
+ return data.toString();
+ }
+ }
+
+
+ /**
+ * Clears the specified value in the given data at the chunk and index.
+ * Note that this method will clear the given chunk if the reference
+ * count becomes zero.
+ *
+ * @return Returns the old value.
+ */
+ private final int clearChunkIndex(int data[][], int chunk, int index) {
+ int value = data[chunk] != null ? data[chunk][index] : -1;
+ if (value != -1) {
+ data[chunk][CHUNK_SIZE]--;
+ data[chunk][index] = -1;
+ if (data[chunk][CHUNK_SIZE] == 0) {
+ data[chunk] = null;
+ }
+ }
+ return value;
+ }
+ private final String clearChunkValue(Object data[][],
+ int chunk, int index) {
+ String value = data[chunk] != null ? (String)data[chunk][index] : null;
+ if (value != null) {
+ data[chunk][index] = null;
+ RefCount c = (RefCount) data[chunk][CHUNK_SIZE];
+ c.fCount--;
+ if (c.fCount == 0) {
+ data[chunk] = null;
+ }
+ }
+ return value;
+ }
+
+ /**
+ * This version of putIdentifier is needed to avoid fluffing
+ * all of the paths to ID attributes when a node object is
+ * created that contains an ID attribute.
+ */
+ private final void putIdentifier0(String idName, Element element) {
+
+ if (DEBUG_IDS) {
+ System.out.println("putIdentifier0("+
+ idName+", "+
+ element+')');
+ }
+
+ // create hashtable
+ if (identifiers == null) {
+ identifiers = new java.util.Hashtable();
+ }
+
+ // save ID and its associated element
+ identifiers.put(idName, element);
+
+ } // putIdentifier0(String,Element)
+
+ /** Prints the ID array. */
+ private static void print(int values[], int start, int end,
+ int middle, int target) {
+
+ if (DEBUG_IDS) {
+ System.out.print(start);
+ System.out.print(" [");
+ for (int i = start; i < end; i++) {
+ if (middle == i) {
+ System.out.print("!");
+ }
+ System.out.print(values[i]);
+ if (values[i] == target) {
+ System.out.print("*");
+ }
+ if (i < end - 1) {
+ System.out.print(" ");
+ }
+ }
+ System.out.println("] "+end);
+ }
+
+ } // print(int[],int,int,int,int)
+
+ //
+ // Classes
+ //
+
+ /**
+ * A simple integer vector.
+ */
+ static final class IntVector {
+
+ //
+ // Data
+ //
+
+ /** Data. */
+ private int data[];
+
+ /** Size. */
+ private int size;
+
+ //
+ // Public methods
+ //
+
+ /** Returns the length of this vector. */
+ public int size() {
+ return size;
+ }
+
+ /** Returns the element at the specified index. */
+ public int elementAt(int index) {
+ return data[index];
+ }
+
+ /** Appends an element to the end of the vector. */
+ public void addElement(int element) {
+ ensureCapacity(size + 1);
+ data[size++] = element;
+ }
+
+ /** Clears the vector. */
+ public void removeAllElements() {
+ size = 0;
+ }
+
+ //
+ // Private methods
+ //
+
+ /** Makes sure that there is enough storage. */
+ private void ensureCapacity(int newsize) {
+
+ if (data == null) {
+ data = new int[newsize + 15];
+ }
+ else if (newsize > data.length) {
+ int newdata[] = new int[newsize + 15];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ data = newdata;
+ }
+
+ } // ensureCapacity(int)
+
+ } // class IntVector
+
+} // class DeferredDocumentImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredDocumentTypeImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredDocumentTypeImpl.java
new file mode 100644
index 0000000..bba39c2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredDocumentTypeImpl.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.Node;
+
+/**
+ * This class represents a Document Type declaraction in
+ * the document itself, not a Document Type Definition (DTD).
+ * An XML document may (or may not) have such a reference.
+ *
+ * DocumentType is an Extended DOM feature, used in XML documents but
+ * not in HTML.
+ *
+ * Note that Entities and Notations are no longer children of the
+ * DocumentType, but are parentless nodes hung only in their
+ * appropriate NamedNodeMaps.
+ *
+ * This area is UNDERSPECIFIED IN REC-DOM-Level-1-19981001
+ * Most notably, absolutely no provision was made for storing
+ * and using Element and Attribute information. Nor was the linkage
+ * between Entities and Entity References nailed down solidly.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DeferredDocumentTypeImpl
+ extends DocumentTypeImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -2172579663227313509L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here.
+ * All other data, can be requested from the ownerDocument via the index.
+ */
+ DeferredDocumentTypeImpl(DeferredDocumentImpl ownerDocument, int nodeIndex) {
+ super(ownerDocument, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncData(true);
+ needsSyncChildren(true);
+
+ } // (DeferredDocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /** Synchronizes the data (name and value) for fast nodes. */
+ protected void synchronizeData() {
+
+ // no need to sync in the future
+ needsSyncData(false);
+
+ // fluff data
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl)this.ownerDocument;
+ name = ownerDocument.getNodeName(fNodeIndex);
+
+ // public and system ids
+ publicID = ownerDocument.getNodeValue(fNodeIndex);
+ systemID = ownerDocument.getNodeURI(fNodeIndex);
+ int extraDataIndex = ownerDocument.getNodeExtra(fNodeIndex);
+ internalSubset = ownerDocument.getNodeValue(extraDataIndex);
+ } // synchronizeData()
+
+ /** Synchronizes the entities, notations, and elements. */
+ protected void synchronizeChildren() {
+
+ // we don't want to generate any event for this so turn them off
+ boolean orig = ownerDocument().getMutationEvents();
+ ownerDocument().setMutationEvents(false);
+
+ // no need to synchronize again
+ needsSyncChildren(false);
+
+ // create new node maps
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl)this.ownerDocument;
+
+ entities = new NamedNodeMapImpl(this);
+ notations = new NamedNodeMapImpl(this);
+ elements = new NamedNodeMapImpl(this);
+
+ // fill node maps
+ DeferredNode last = null;
+ for (int index = ownerDocument.getLastChild(fNodeIndex);
+ index != -1;
+ index = ownerDocument.getPrevSibling(index)) {
+
+ DeferredNode node = ownerDocument.getNodeObject(index);
+ int type = node.getNodeType();
+ switch (type) {
+
+ // internal, external, and unparsed entities
+ case Node.ENTITY_NODE: {
+ entities.setNamedItem(node);
+ break;
+ }
+
+ // notations
+ case Node.NOTATION_NODE: {
+ notations.setNamedItem(node);
+ break;
+ }
+
+ // element definitions
+ case NodeImpl.ELEMENT_DEFINITION_NODE: {
+ elements.setNamedItem(node);
+ break;
+ }
+
+ // elements
+ case Node.ELEMENT_NODE: {
+ if (((DocumentImpl)getOwnerDocument()).allowGrammarAccess){
+ insertBefore(node, last);
+ last = node;
+ break;
+ }
+ }
+
+ // NOTE: Should never get here! -Ac
+ default: {
+ System.out.println("DeferredDocumentTypeImpl" +
+ "#synchronizeInfo: " +
+ "node.getNodeType() = " +
+ node.getNodeType() +
+ ", class = " +
+ node.getClass().getName());
+ }
+ }
+ }
+
+ // set mutation events flag back to its original value
+ ownerDocument().setMutationEvents(orig);
+
+ // set entities and notations read_only per DOM spec
+ setReadOnly(true, false);
+
+ } // synchronizeChildren()
+
+} // class DeferredDocumentTypeImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredElementDefinitionImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredElementDefinitionImpl.java
new file mode 100644
index 0000000..2913a63
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredElementDefinitionImpl.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.Node;
+
+/**
+ * NON-DOM CLASS: Describe one of the Elements (and its associated
+ * Attributes) defined in this Document Type.
+ *
+ * I've included this in Level 1 purely as an anchor point for default
+ * attributes. In Level 2 it should enable the ChildRule support.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class DeferredElementDefinitionImpl
+ extends ElementDefinitionImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 6703238199538041591L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here.
+ * All other data, can be requested from the ownerDocument via the index.
+ */
+ DeferredElementDefinitionImpl(DeferredDocumentImpl ownerDocument,
+ int nodeIndex) {
+ super(ownerDocument, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncData(true);
+ needsSyncChildren(true);
+
+ } // (DeferredDocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /** Synchronizes the data (name and value) for fast nodes. */
+ protected void synchronizeData() {
+
+ // no need to sync in the future
+ needsSyncData(false);
+
+ // fluff data
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl)this.ownerDocument;
+ name = ownerDocument.getNodeName(fNodeIndex);
+
+ } // synchronizeData()
+
+ /** Synchronizes the default attribute values. */
+ protected void synchronizeChildren() {
+
+ // we don't want to generate any event for this so turn them off
+ boolean orig = ownerDocument.getMutationEvents();
+ ownerDocument.setMutationEvents(false);
+
+ // attributes are now synced
+ needsSyncChildren(false);
+
+ // create attributes node map
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl)this.ownerDocument;
+ attributes = new NamedNodeMapImpl(ownerDocument);
+
+ // Default attributes dangle as children of the element
+ // definition "node" in the internal fast table.
+ for (int nodeIndex = ownerDocument.getLastChild(fNodeIndex);
+ nodeIndex != -1;
+ nodeIndex = ownerDocument.getPrevSibling(nodeIndex)) {
+ Node attr = ownerDocument.getNodeObject(nodeIndex);
+ attributes.setNamedItem(attr);
+ }
+
+ // set mutation events flag back to its original value
+ ownerDocument.setMutationEvents(orig);
+
+ } // synchronizeChildren()
+
+} // class DeferredElementDefinitionImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredElementImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredElementImpl.java
new file mode 100644
index 0000000..ee09d2a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredElementImpl.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * WARNING: because java doesn't support multi-inheritance some code is
+ * duplicated. If you're changing this file you probably want to change
+ * DeferredElementNSImpl.java at the same time.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.NamedNodeMap;
+
+/**
+ * Elements represent most of the "markup" and structure of the
+ * document. They contain both the data for the element itself
+ * (element name and attributes), and any contained nodes, including
+ * document text (as children).
+ *
+ * Elements may have Attributes associated with them; the API for this is
+ * defined in Node, but the function is implemented here. In general, XML
+ * applications should retrive Attributes as Nodes, since they may contain
+ * entity references and hence be a fairly complex sub-tree. HTML users will
+ * be dealing with simple string values, and convenience methods are provided
+ * to work in terms of Strings.
+ *
+ * DeferredElementImpl inherits from ElementImpl which does not support
+ * Namespaces. DeferredElementNSImpl, which inherits from ElementNSImpl, does.
+ * @see DeferredElementNSImpl
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DeferredElementImpl
+ extends ElementImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -7670981133940934842L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here. All
+ * other data, can be requested from the ownerDocument via the index.
+ */
+ DeferredElementImpl(DeferredDocumentImpl ownerDoc, int nodeIndex) {
+ super(ownerDoc, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncChildren(true);
+
+ } // (DocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public final int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /** Synchronizes the data (name and value) for fast nodes. */
+ protected final void synchronizeData() {
+
+ // no need to sync in the future
+ needsSyncData(false);
+
+ // fluff data
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl)this.ownerDocument;
+
+ // we don't want to generate any event for this so turn them off
+ boolean orig = ownerDocument.mutationEvents;
+ ownerDocument.mutationEvents = false;
+
+ name = ownerDocument.getNodeName(fNodeIndex);
+
+ // attributes
+ setupDefaultAttributes();
+ int index = ownerDocument.getNodeExtra(fNodeIndex);
+ if (index != -1) {
+ NamedNodeMap attrs = getAttributes();
+ do {
+ NodeImpl attr = (NodeImpl)ownerDocument.getNodeObject(index);
+ attrs.setNamedItem(attr);
+ index = ownerDocument.getPrevSibling(index);
+ } while (index != -1);
+ }
+
+ // set mutation events flag back to its original value
+ ownerDocument.mutationEvents = orig;
+
+ } // synchronizeData()
+
+ protected final void synchronizeChildren() {
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) ownerDocument();
+ ownerDocument.synchronizeChildren(this, fNodeIndex);
+ } // synchronizeChildren()
+
+} // class DeferredElementImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredElementNSImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredElementNSImpl.java
new file mode 100644
index 0000000..bfb0b8f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredElementNSImpl.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/*
+ * WARNING: because java doesn't support multi-inheritance some code is
+ * duplicated. If you're changing this file you probably want to change
+ * DeferredElementImpl.java at the same time.
+ *
+ * @version $Id$
+ */
+
+package org.apache.xerces.dom;
+
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xs.XSTypeDefinition;
+import org.w3c.dom.NamedNodeMap;
+
+/**
+ * DeferredElementNSImpl is to ElementNSImpl, what DeferredElementImpl is to
+ * ElementImpl.
+ *
+ * @xerces.internal
+ *
+ * @see DeferredElementImpl
+ */
+public class DeferredElementNSImpl
+ extends ElementNSImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -5001885145370927385L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here. All
+ * other data, can be requested from the ownerDocument via the index.
+ */
+ DeferredElementNSImpl(DeferredDocumentImpl ownerDoc, int nodeIndex) {
+ super(ownerDoc, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncChildren(true);
+
+ } // (DocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public final int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /** Synchronizes the data (name and value) for fast nodes. */
+ protected final void synchronizeData() {
+
+ // no need to sync in the future
+ needsSyncData(false);
+
+ // fluff data
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) this.ownerDocument;
+
+ // we don't want to generate any event for this so turn them off
+ boolean orig = ownerDocument.mutationEvents;
+ ownerDocument.mutationEvents = false;
+
+ name = ownerDocument.getNodeName(fNodeIndex);
+
+ // extract local part from QName
+ int index = name.indexOf(':');
+ if (index < 0) {
+ localName = name;
+ }
+ else {
+ localName = name.substring(index + 1);
+ }
+
+ namespaceURI = ownerDocument.getNodeURI(fNodeIndex);
+ type = (XSTypeDefinition)ownerDocument.getTypeInfo(fNodeIndex);
+
+ // attributes
+ setupDefaultAttributes();
+ int attrIndex = ownerDocument.getNodeExtra(fNodeIndex);
+ if (attrIndex != -1) {
+ NamedNodeMap attrs = getAttributes();
+ boolean seenSchemaDefault = false;
+ do {
+ AttrImpl attr = (AttrImpl) ownerDocument.getNodeObject(attrIndex);
+ // Take special care of schema defaulted attributes. Calling the
+ // non-namespace aware setAttributeNode() method could overwrite
+ // another attribute with the same local name.
+ if (!attr.getSpecified() && (seenSchemaDefault ||
+ (attr.getNamespaceURI() != null &&
+ attr.getNamespaceURI() != NamespaceContext.XMLNS_URI &&
+ attr.getName().indexOf(':') < 0))) {
+ seenSchemaDefault = true;
+ attrs.setNamedItemNS(attr);
+ }
+ else {
+ attrs.setNamedItem(attr);
+ }
+ attrIndex = ownerDocument.getPrevSibling(attrIndex);
+ } while (attrIndex != -1);
+ }
+
+ // set mutation events flag back to its original value
+ ownerDocument.mutationEvents = orig;
+
+ } // synchronizeData()
+
+ /**
+ * Synchronizes the node's children with the internal structure.
+ * Fluffing the children at once solves a lot of work to keep
+ * the two structures in sync. The problem gets worse when
+ * editing the tree -- this makes it a lot easier.
+ */
+ protected final void synchronizeChildren() {
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) ownerDocument();
+ ownerDocument.synchronizeChildren(this, fNodeIndex);
+ } // synchronizeChildren()
+
+} // class DeferredElementImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredEntityImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredEntityImpl.java
new file mode 100644
index 0000000..269d1c5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredEntityImpl.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+
+/**
+ * Entity nodes hold the reference data for an XML Entity -- either
+ * parsed or unparsed. The nodeName (inherited from Node) will contain
+ * the name (if any) of the Entity. Its data will be contained in the
+ * Entity's children, in exactly the structure which an
+ * EntityReference to this name will present within the document's
+ * body.
+ *
+ * Note that this object models the actual entity, _not_ the entity
+ * declaration or the entity reference.
+ *
+ * An XML processor may choose to completely expand entities before
+ * the structure model is passed to the DOM; in this case, there will
+ * be no EntityReferences in the DOM tree.
+ *
+ * Quoting the 10/01 DOM Proposal,
+ *
+ * "The DOM Level 1 does not support editing Entity nodes; if a user
+ * wants to make changes to the contents of an Entity, every related
+ * EntityReference node has to be replaced in the structure model by
+ * a clone of the Entity's contents, and then the desired changes
+ * must be made to each of those clones instead. All the
+ * descendants of an Entity node are readonly."
+ *
+ * I'm interpreting this as: It is the parser's responsibilty to call
+ * the non-DOM operation setReadOnly(true,true) after it constructs
+ * the Entity. Since the DOM explicitly decided not to deal with this,
+ * _any_ answer will involve a non-DOM operation, and this is the
+ * simplest solution.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DeferredEntityImpl
+ extends EntityImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 4760180431078941638L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here.
+ * All other data, can be requested from the ownerDocument via the index.
+ */
+ DeferredEntityImpl(DeferredDocumentImpl ownerDocument, int nodeIndex) {
+ super(ownerDocument, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncData(true);
+ needsSyncChildren(true);
+
+ } // (DeferredDocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * Synchronize the entity data. This is special because of the way
+ * that the "fast" version stores the information.
+ */
+ protected void synchronizeData() {
+
+ // no need to sychronize again
+ needsSyncData(false);
+
+ // get the node data
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl)this.ownerDocument;
+ name = ownerDocument.getNodeName(fNodeIndex);
+
+ // get the entity data
+ publicId = ownerDocument.getNodeValue(fNodeIndex);
+ systemId = ownerDocument.getNodeURI(fNodeIndex);
+ int extraDataIndex = ownerDocument.getNodeExtra(fNodeIndex);
+ ownerDocument.getNodeType(extraDataIndex);
+
+ notationName = ownerDocument.getNodeName(extraDataIndex);
+
+ // encoding and version DOM L3
+ version = ownerDocument.getNodeValue(extraDataIndex);
+ encoding = ownerDocument.getNodeURI(extraDataIndex);
+
+ // baseURI, actualEncoding DOM L3
+ int extraIndex2 = ownerDocument.getNodeExtra(extraDataIndex);
+ baseURI = ownerDocument.getNodeName(extraIndex2);
+ inputEncoding = ownerDocument.getNodeValue(extraIndex2);
+
+ } // synchronizeData()
+
+ /** Synchronize the children. */
+ protected void synchronizeChildren() {
+
+ // no need to synchronize again
+ needsSyncChildren(false);
+
+ isReadOnly(false);
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) ownerDocument();
+ ownerDocument.synchronizeChildren(this, fNodeIndex);
+ setReadOnly(true, true);
+
+ } // synchronizeChildren()
+
+} // class DeferredEntityImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredEntityReferenceImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredEntityReferenceImpl.java
new file mode 100644
index 0000000..1fab9d6
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredEntityReferenceImpl.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+/**
+ * EntityReference models the XML &entityname; syntax, when used for
+ * entities defined by the DOM. Entities hardcoded into XML, such as
+ * character entities, should instead have been translated into text
+ * by the code which generated the DOM tree.
+ *
+ * An XML processor has the alternative of fully expanding Entities
+ * into the normal document tree. If it does so, no EntityReference nodes
+ * will appear.
+ *
+ * Similarly, non-validating XML processors are not required to read
+ * or process entity declarations made in the external subset or
+ * declared in external parameter entities. Hence, some applications
+ * may not make the replacement value available for Parsed Entities
+ * of these types.
+ *
+ * EntityReference behaves as a read-only node, and the children of
+ * the EntityReference (which reflect those of the Entity, and should
+ * also be read-only) give its replacement value, if any. They are
+ * supposed to automagically stay in synch if the DocumentType is
+ * updated with new values for the Entity.
+ *
+ * The defined behavior makes efficient storage difficult for the DOM
+ * implementor. We can't just look aside to the Entity's definition
+ * in the DocumentType since those nodes have the wrong parent (unless
+ * we can come up with a clever "imaginary parent" mechanism). We
+ * must at least appear to clone those children... which raises the
+ * issue of keeping the reference synchronized with its parent.
+ * This leads me back to the "cached image of centrally defined data"
+ * solution, much as I dislike it.
+ *
+ * For now I have decided, since REC-DOM-Level-1-19980818 doesn't
+ * cover this in much detail, that synchronization doesn't have to be
+ * considered while the user is deep in the tree. That is, if you're
+ * looking within one of the EntityReferennce's children and the Entity
+ * changes, you won't be informed; instead, you will continue to access
+ * the same object -- which may or may not still be part of the tree.
+ * This is the same behavior that obtains elsewhere in the DOM if the
+ * subtree you're looking at is deleted from its parent, so it's
+ * acceptable here. (If it really bothers folks, we could set things
+ * up so deleted subtrees are walked and marked invalid, but that's
+ * not part of the DOM's defined behavior.)
+ *
+ * As a result, only the EntityReference itself has to be aware of
+ * changes in the Entity. And it can take advantage of the same
+ * structure-change-monitoring code I implemented to support
+ * DeepNodeList.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DeferredEntityReferenceImpl
+ extends EntityReferenceImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 390319091370032223L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here.
+ * All other data, can be requested from the ownerDocument via the index.
+ */
+ DeferredEntityReferenceImpl(DeferredDocumentImpl ownerDocument,
+ int nodeIndex) {
+ super(ownerDocument, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncData(true);
+
+ } // (DeferredDocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * Synchronize the entity data. This is special because of the way
+ * that the "fast" version stores the information.
+ */
+ protected void synchronizeData() {
+
+ // no need to sychronize again
+ needsSyncData(false);
+
+ // get the node data
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl)this.ownerDocument;
+ name = ownerDocument.getNodeName(fNodeIndex);
+ baseURI = ownerDocument.getNodeValue(fNodeIndex);
+
+ } // synchronizeData()
+
+ /** Synchronize the children. */
+ protected void synchronizeChildren() {
+
+ // no need to synchronize again
+ needsSyncChildren(false);
+
+ // get children
+ isReadOnly(false);
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) ownerDocument();
+ ownerDocument.synchronizeChildren(this, fNodeIndex);
+ setReadOnly(true, true);
+
+ } // synchronizeChildren()
+
+} // class DeferredEntityReferenceImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredNode.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredNode.java
new file mode 100644
index 0000000..f54376a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredNode.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.Node;
+
+/**
+ * An interface for deferred node object.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public interface DeferredNode extends Node {
+
+
+ public static final short TYPE_NODE = 20;
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex();
+
+} // interface DeferredNode
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredNotationImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredNotationImpl.java
new file mode 100644
index 0000000..ce8c600
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredNotationImpl.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+/**
+ * Notations are how the Document Type Description (DTD) records hints
+ * about the format of an XML "unparsed entity" -- in other words,
+ * non-XML data bound to this document type, which some applications
+ * may wish to consult when manipulating the document. A Notation
+ * represents a name-value pair, with its nodeName being set to the
+ * declared name of the notation.
+ *
+ * Notations are also used to formally declare the "targets" of
+ * Processing Instructions.
+ *
+ * Note that the Notation's data is non-DOM information; the DOM only
+ * records what and where it is.
+ *
+ * See the XML 1.0 spec, sections 4.7 and 2.6, for more info.
+ *
+ * Level 1 of the DOM does not support editing Notation contents.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DeferredNotationImpl
+ extends NotationImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 5705337172887990848L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here.
+ * All other data, can be requested from the ownerDocument via the index.
+ */
+ DeferredNotationImpl(DeferredDocumentImpl ownerDocument, int nodeIndex) {
+ super(ownerDocument, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncData(true);
+
+ } // (DeferredDocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * Synchronizes the data. This is special because of the way
+ * that the "fast" notation stores its information internally.
+ */
+ protected void synchronizeData() {
+
+ // no need to synchronize again
+ needsSyncData(false);
+
+ // name
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl)this.ownerDocument();
+ name = ownerDocument.getNodeName(fNodeIndex);
+
+ ownerDocument.getNodeType(fNodeIndex);
+ // public and system ids
+ publicId = ownerDocument.getNodeValue(fNodeIndex);
+ systemId = ownerDocument.getNodeURI(fNodeIndex);
+ int extraDataIndex = ownerDocument.getNodeExtra(fNodeIndex);
+ ownerDocument.getNodeType(extraDataIndex);
+ baseURI = ownerDocument.getNodeName(extraDataIndex);
+
+
+ } // synchronizeData()
+
+} // class DeferredNotationImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredProcessingInstructionImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredProcessingInstructionImpl.java
new file mode 100644
index 0000000..c1f2f90
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredProcessingInstructionImpl.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+/**
+ * Processing Instructions (PIs) permit documents to carry
+ * processor-specific information alongside their actual content. PIs
+ * are most common in XML, but they are supported in HTML as well.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DeferredProcessingInstructionImpl
+ extends ProcessingInstructionImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -4643577954293565388L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here.
+ * All other data, can be requested from the ownerDocument via the index.
+ */
+ DeferredProcessingInstructionImpl(DeferredDocumentImpl ownerDocument,
+ int nodeIndex) {
+ super(ownerDocument, null, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncData(true);
+
+ } // (DeferredDocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /** Synchronizes the data. */
+ protected void synchronizeData() {
+
+ // no need to sync in the future
+ needsSyncData(false);
+
+ // fluff data
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) this.ownerDocument();
+ target = ownerDocument.getNodeName(fNodeIndex);
+ data = ownerDocument.getNodeValueString(fNodeIndex);
+
+ } // synchronizeData()
+
+} // class DeferredProcessingInstructionImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DeferredTextImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredTextImpl.java
new file mode 100644
index 0000000..e17dced
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DeferredTextImpl.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+/**
+ * Text nodes hold the non-markup, non-Entity content of
+ * an Element or Attribute.
+ *
+ * When a document is first made available to the DOM, there is only
+ * one Text object for each block of adjacent plain-text. Users (ie,
+ * applications) may create multiple adjacent Texts during editing --
+ * see {@link org.w3c.dom.Element#normalize} for discussion.
+ *
+ * Note that CDATASection is a subclass of Text. This is conceptually
+ * valid, since they're really just two different ways of quoting
+ * characters when they're written out as part of an XML stream.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DeferredTextImpl
+ extends TextImpl
+ implements DeferredNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 2310613872100393425L;
+
+ //
+ // Data
+ //
+
+ /** Node index. */
+ protected transient int fNodeIndex;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * This is the deferred constructor. Only the fNodeIndex is given here.
+ * All other data, can be requested from the ownerDocument via the index.
+ */
+ DeferredTextImpl(DeferredDocumentImpl ownerDocument, int nodeIndex) {
+ super(ownerDocument, null);
+
+ fNodeIndex = nodeIndex;
+ needsSyncData(true);
+
+ } // (DeferredDocumentImpl,int)
+
+ //
+ // DeferredNode methods
+ //
+
+ /** Returns the node index. */
+ public int getNodeIndex() {
+ return fNodeIndex;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /** Synchronizes the underlying data. */
+ protected void synchronizeData() {
+
+ // no need for future synchronizations
+ needsSyncData(false);
+
+ // get initial text value
+ DeferredDocumentImpl ownerDocument =
+ (DeferredDocumentImpl) this.ownerDocument();
+ data = ownerDocument.getNodeValueString(fNodeIndex);
+
+ // NOTE: We used to normalize adjacent text node values here.
+ // This code has moved to the DeferredDocumentImpl
+ // getNodeValueString() method. -Ac
+
+ // ignorable whitespace
+ isIgnorableWhitespace(ownerDocument.getNodeExtra(fNodeIndex) == 1);
+
+ } // synchronizeData()
+
+} // class DeferredTextImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DocumentFragmentImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DocumentFragmentImpl.java
new file mode 100644
index 0000000..b5cdd6b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DocumentFragmentImpl.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+/**
+ * DocumentFragment is a "lightweight" or "minimal" Document
+ * object. It is very common to want to be able to extract a portion
+ * of a document's tree or to create a new fragment of a
+ * document. Imagine implementing a user command like cut or
+ * rearranging a document by moving fragments around. It is desirable
+ * to have an object which can hold such fragments and it is quite
+ * natural to use a Node for this purpose. While it is true that a
+ * Document object could fulfil this role, a Document object can
+ * potentially be a heavyweight object, depending on the underlying
+ * implementation... and in DOM Level 1, nodes aren't allowed to cross
+ * Document boundaries anyway. What is really needed for this is a
+ * very lightweight object. DocumentFragment is such an object.
+ *
+ * Furthermore, various operations -- such as inserting nodes as
+ * children of another Node -- may take DocumentFragment objects as
+ * arguments; this results in all the child nodes of the
+ * DocumentFragment being moved to the child list of this node.
+ *
+ * The children of a DocumentFragment node are zero or more nodes
+ * representing the tops of any sub-trees defining the structure of
+ * the document. DocumentFragment do not need to be well-formed XML
+ * documents (although they do need to follow the rules imposed upon
+ * well-formed XML parsed entities, which can have multiple top
+ * nodes). For example, a DocumentFragment might have only one child
+ * and that child node could be a Text node. Such a structure model
+ * represents neither an HTML document nor a well-formed XML document.
+ *
+ * When a DocumentFragment is inserted into a Document (or indeed any
+ * other Node that may take children) the children of the
+ * DocumentFragment and not the DocumentFragment itself are inserted
+ * into the Node. This makes the DocumentFragment very useful when the
+ * user wishes to create nodes that are siblings; the DocumentFragment
+ * acts as the parent of these nodes so that the user can use the
+ * standard methods from the Node interface, such as insertBefore()
+ * and appendChild().
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DocumentFragmentImpl
+ extends ParentNode
+ implements DocumentFragment {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -7596449967279236746L;
+
+ //
+ // Constructors
+ //
+
+ /** Factory constructor. */
+ public DocumentFragmentImpl(CoreDocumentImpl ownerDoc) {
+ super(ownerDoc);
+ }
+
+ /** Constructor for serialization. */
+ public DocumentFragmentImpl() {}
+
+ //
+ // Node methods
+ //
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public short getNodeType() {
+ return Node.DOCUMENT_FRAGMENT_NODE;
+ }
+
+ /** Returns the node name. */
+ public String getNodeName() {
+ return "#document-fragment";
+ }
+
+ /**
+ * Override default behavior to call normalize() on this Node's
+ * children. It is up to implementors or Node to override normalize()
+ * to take action.
+ */
+ public void normalize() {
+ // No need to normalize if already normalized.
+ if (isNormalized()) {
+ return;
+ }
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ ChildNode kid, next;
+
+ for (kid = firstChild; kid != null; kid = next) {
+ next = kid.nextSibling;
+
+ // If kid is a text node, we need to check for one of two
+ // conditions:
+ // 1) There is an adjacent text node
+ // 2) There is no adjacent text node, but kid is
+ // an empty text node.
+ if ( kid.getNodeType() == Node.TEXT_NODE )
+ {
+ // If an adjacent text node, merge it with kid
+ if ( next!=null && next.getNodeType() == Node.TEXT_NODE )
+ {
+ ((Text)kid).appendData(next.getNodeValue());
+ removeChild( next );
+ next = kid; // Don't advance; there might be another.
+ }
+ else
+ {
+ // If kid is empty, remove it
+ if ( kid.getNodeValue() == null || kid.getNodeValue().length() == 0 ) {
+ removeChild( kid );
+ }
+ }
+ }
+
+ kid.normalize();
+ }
+
+ isNormalized(true);
+ }
+
+} // class DocumentFragmentImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DocumentImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DocumentImpl.java
new file mode 100644
index 0000000..c4005aa
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DocumentImpl.java
@@ -0,0 +1,1486 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.Serializable;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.xerces.dom.events.EventImpl;
+import org.apache.xerces.dom.events.MouseEventImpl;
+import org.apache.xerces.dom.events.MutationEventImpl;
+import org.apache.xerces.dom.events.UIEventImpl;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.UserDataHandler;
+import org.w3c.dom.events.DocumentEvent;
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventException;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.events.MutationEvent;
+import org.w3c.dom.ranges.DocumentRange;
+import org.w3c.dom.ranges.Range;
+import org.w3c.dom.traversal.DocumentTraversal;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+import org.w3c.dom.traversal.TreeWalker;
+
+
+/**
+ * The Document interface represents the entire HTML or XML document.
+ * Conceptually, it is the root of the document tree, and provides the
+ * primary access to the document's data.
+ *
+ * Since elements, text nodes, comments, processing instructions,
+ * etc. cannot exist outside the context of a Document, the Document
+ * interface also contains the factory methods needed to create these
+ * objects. The Node objects created have a ownerDocument attribute
+ * which associates them with the Document within whose context they
+ * were created.
+ *
+ * The DocumentImpl class also implements the DOM Level 2 DocumentTraversal
+ * interface. This interface is comprised of factory methods needed to
+ * create NodeIterators and TreeWalkers. The process of creating NodeIterator
+ * objects also adds these references to this document.
+ * After finishing with an iterator it is important to remove the object
+ * using the remove methods in this implementation. This allows the release of
+ * the references from the iterator objects to the DOM Nodes.
+ *
+ * Note: When any node in the document is serialized, the
+ * entire document is serialized along with it.
+ *
+ * @xerces.internal
+ *
+ * @author Arnaud Le Hors, IBM
+ * @author Joe Kesselman, IBM
+ * @author Andy Clark, IBM
+ * @author Ralf Pfeiffer, IBM
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DocumentImpl
+ extends CoreDocumentImpl
+ implements DocumentTraversal, DocumentEvent, DocumentRange {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 515687835542616694L;
+
+ //
+ // Data
+ //
+
+ /** Node Iterators */
+ protected transient List iterators;
+
+ /** Reference queue for cleared Node Iterator references */
+ protected transient ReferenceQueue iteratorReferenceQueue;
+
+ /** Ranges */
+ protected transient List ranges;
+
+ /** Reference queue for cleared Range references */
+ protected transient ReferenceQueue rangeReferenceQueue;
+
+ /** Table for event listeners registered to this document nodes. */
+ protected Hashtable eventListeners;
+
+ /** Bypass mutation events firing. */
+ protected boolean mutationEvents = false;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * NON-DOM: Actually creating a Document is outside the DOM's spec,
+ * since it has to operate in terms of a particular implementation.
+ */
+ public DocumentImpl() {
+ super();
+ }
+
+ /** Constructor. */
+ public DocumentImpl(boolean grammarAccess) {
+ super(grammarAccess);
+ }
+
+ /**
+ * For DOM2 support.
+ * The createDocument factory method is in DOMImplementation.
+ */
+ public DocumentImpl(DocumentType doctype)
+ {
+ super(doctype);
+ }
+
+ /** For DOM2 support. */
+ public DocumentImpl(DocumentType doctype, boolean grammarAccess) {
+ super(doctype, grammarAccess);
+ }
+
+ //
+ // Node methods
+ //
+
+ /**
+ * Deep-clone a document, including fixing ownerDoc for the cloned
+ * children. Note that this requires bypassing the WRONG_DOCUMENT_ERR
+ * protection. I've chosen to implement it by calling importNode
+ * which is DOM Level 2.
+ *
+ * @return org.w3c.dom.Node
+ * @param deep boolean, iff true replicate children
+ */
+ public Node cloneNode(boolean deep) {
+
+ DocumentImpl newdoc = new DocumentImpl();
+ callUserDataHandlers(this, newdoc, UserDataHandler.NODE_CLONED);
+ cloneNode(newdoc, deep);
+
+ // experimental
+ newdoc.mutationEvents = mutationEvents;
+
+ return newdoc;
+
+ } // cloneNode(boolean):Node
+
+ /**
+ * Retrieve information describing the abilities of this particular
+ * DOM implementation. Intended to support applications that may be
+ * using DOMs retrieved from several different sources, potentially
+ * with different underlying representations.
+ */
+ public DOMImplementation getImplementation() {
+ // Currently implemented as a singleton, since it's hardcoded
+ // information anyway.
+ return DOMImplementationImpl.getDOMImplementation();
+ }
+
+ //
+ // DocumentTraversal methods
+ //
+
+ /**
+ * NON-DOM extension:
+ * Create and return a NodeIterator. The NodeIterator is
+ * added to a list of NodeIterators so that it can be
+ * removed to free up the DOM Nodes it references.
+ *
+ * @param root The root of the iterator.
+ * @param whatToShow The whatToShow mask.
+ * @param filter The NodeFilter installed. Null means no filter.
+ */
+ public NodeIterator createNodeIterator(Node root,
+ short whatToShow,
+ NodeFilter filter)
+ {
+ return createNodeIterator(root, whatToShow, filter, true);
+ }
+
+ /**
+ * Create and return a NodeIterator. The NodeIterator is
+ * added to a list of NodeIterators so that it can be
+ * removed to free up the DOM Nodes it references.
+ *
+ * @param root The root of the iterator.
+ * @param whatToShow The whatToShow mask.
+ * @param filter The NodeFilter installed. Null means no filter.
+ * @param entityReferenceExpansion true to expand the contents of
+ * EntityReference nodes
+ * @since WD-DOM-Level-2-19990923
+ */
+ public NodeIterator createNodeIterator(Node root,
+ int whatToShow,
+ NodeFilter filter,
+ boolean entityReferenceExpansion)
+ {
+
+ if (root == null) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ NodeIterator iterator = new NodeIteratorImpl(this,
+ root,
+ whatToShow,
+ filter,
+ entityReferenceExpansion);
+ if (iterators == null) {
+ iterators = new LinkedList();
+ iteratorReferenceQueue = new ReferenceQueue();
+ }
+
+ removeStaleIteratorReferences();
+ iterators.add(new WeakReference(iterator, iteratorReferenceQueue));
+
+ return iterator;
+ }
+
+ /**
+ * NON-DOM extension:
+ * Create and return a TreeWalker.
+ *
+ * @param root The root of the iterator.
+ * @param whatToShow The whatToShow mask.
+ * @param filter The NodeFilter installed. Null means no filter.
+ */
+ public TreeWalker createTreeWalker(Node root,
+ short whatToShow,
+ NodeFilter filter)
+ {
+ return createTreeWalker(root, whatToShow, filter, true);
+ }
+ /**
+ * Create and return a TreeWalker.
+ *
+ * @param root The root of the iterator.
+ * @param whatToShow The whatToShow mask.
+ * @param filter The NodeFilter installed. Null means no filter.
+ * @param entityReferenceExpansion true to expand the contents of
+ * EntityReference nodes
+ * @since WD-DOM-Level-2-19990923
+ */
+ public TreeWalker createTreeWalker(Node root,
+ int whatToShow,
+ NodeFilter filter,
+ boolean entityReferenceExpansion)
+ {
+ if (root == null) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+ return new TreeWalkerImpl(root, whatToShow, filter,
+ entityReferenceExpansion);
+ }
+
+ //
+ // Not DOM Level 2. Support DocumentTraversal methods.
+ //
+
+ /**
+ * This is not called by the developer client. The
+ * developer client uses the detach() function on the
+ * NodeIterator itself.
+ *
+ * This function is called from the NodeIterator#detach().
+ */
+ void removeNodeIterator(NodeIterator nodeIterator) {
+
+ if (nodeIterator == null) return;
+ if (iterators == null) return;
+
+ removeStaleIteratorReferences();
+ Iterator i = iterators.iterator();
+ while (i.hasNext()) {
+ Object iterator = ((Reference) i.next()).get();
+ if (iterator == nodeIterator) {
+ i.remove();
+ return;
+ }
+ // Remove stale reference from the list.
+ else if (iterator == null) {
+ i.remove();
+ }
+ }
+ }
+
+ /**
+ * Remove stale iterator references from the iterator list.
+ */
+ private void removeStaleIteratorReferences() {
+ removeStaleReferences(iteratorReferenceQueue, iterators);
+ }
+
+ /**
+ * Remove stale references from the given list.
+ */
+ private void removeStaleReferences(ReferenceQueue queue, List list) {
+ Reference ref = queue.poll();
+ int count = 0;
+ while (ref != null) {
+ ++count;
+ ref = queue.poll();
+ }
+ if (count > 0) {
+ final Iterator i = list.iterator();
+ while (i.hasNext()) {
+ Object o = ((Reference) i.next()).get();
+ if (o == null) {
+ i.remove();
+ if (--count <= 0) {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // DocumentRange methods
+ //
+ /**
+ */
+ public Range createRange() {
+
+ if (ranges == null) {
+ ranges = new LinkedList();
+ rangeReferenceQueue = new ReferenceQueue();
+ }
+
+ Range range = new RangeImpl(this);
+
+ removeStaleRangeReferences();
+ ranges.add(new WeakReference(range, rangeReferenceQueue));
+
+ return range;
+
+ }
+
+ /** Not a client function. Called by Range.detach(),
+ * so a Range can remove itself from the list of
+ * Ranges.
+ */
+ void removeRange(Range range) {
+
+ if (range == null) return;
+ if (ranges == null) return;
+
+ removeStaleRangeReferences();
+ Iterator i = ranges.iterator();
+ while (i.hasNext()) {
+ Object otherRange = ((Reference) i.next()).get();
+ if (otherRange == range) {
+ i.remove();
+ return;
+ }
+ // Remove stale reference from the list.
+ else if (otherRange == null) {
+ i.remove();
+ }
+ }
+ }
+
+ /**
+ * A method to be called when some text was changed in a text node,
+ * so that live objects can be notified.
+ */
+ void replacedText(CharacterDataImpl node) {
+ // notify ranges
+ if (ranges != null) {
+ notifyRangesReplacedText(node);
+ }
+ }
+
+ private void notifyRangesReplacedText(CharacterDataImpl node) {
+ removeStaleRangeReferences();
+ final Iterator i = ranges.iterator();
+ while (i.hasNext()) {
+ RangeImpl range = (RangeImpl) ((Reference) i.next()).get();
+ if (range != null) {
+ range.receiveReplacedText(node);
+ }
+ // Remove stale reference from the list.
+ else {
+ i.remove();
+ }
+ }
+ }
+
+ /**
+ * A method to be called when some text was deleted from a text node,
+ * so that live objects can be notified.
+ */
+ void deletedText(CharacterDataImpl node, int offset, int count) {
+ // notify ranges
+ if (ranges != null) {
+ notifyRangesDeletedText(node, offset, count);
+ }
+ }
+
+ private void notifyRangesDeletedText(CharacterDataImpl node, int offset, int count) {
+ removeStaleRangeReferences();
+ final Iterator i = ranges.iterator();
+ while (i.hasNext()) {
+ RangeImpl range = (RangeImpl) ((Reference) i.next()).get();
+ if (range != null) {
+ range.receiveDeletedText(node, offset, count);
+ }
+ // Remove stale reference from the list.
+ else {
+ i.remove();
+ }
+ }
+ }
+
+ /**
+ * A method to be called when some text was inserted into a text node,
+ * so that live objects can be notified.
+ */
+ void insertedText(CharacterDataImpl node, int offset, int count) {
+ // notify ranges
+ if (ranges != null) {
+ notifyRangesInsertedText(node, offset, count);
+ }
+ }
+
+ private void notifyRangesInsertedText(CharacterDataImpl node, int offset, int count) {
+ removeStaleRangeReferences();
+ final Iterator i = ranges.iterator();
+ while (i.hasNext()) {
+ RangeImpl range = (RangeImpl) ((Reference) i.next()).get();
+ if (range != null) {
+ range.receiveInsertedText(node, offset, count);
+ }
+ // Remove stale reference from the list.
+ else {
+ i.remove();
+ }
+ }
+ }
+
+ /**
+ * A method to be called when a text node has been split,
+ * so that live objects can be notified.
+ */
+ void splitData(Node node, Node newNode, int offset) {
+ // notify ranges
+ if (ranges != null) {
+ notifyRangesSplitData(node, newNode, offset);
+ }
+ }
+
+ private void notifyRangesSplitData(Node node, Node newNode, int offset) {
+ removeStaleRangeReferences();
+ final Iterator i = ranges.iterator();
+ while (i.hasNext()) {
+ RangeImpl range = (RangeImpl) ((Reference) i.next()).get();
+ if (range != null) {
+ range.receiveSplitData(node, newNode, offset);
+ }
+ // Remove stale reference from the list.
+ else {
+ i.remove();
+ }
+ }
+ }
+
+ /**
+ * Remove stale range references from the range list.
+ */
+ private void removeStaleRangeReferences() {
+ removeStaleReferences(rangeReferenceQueue, ranges);
+ }
+
+ //
+ // DocumentEvent methods
+ //
+
+ /**
+ * Introduced in DOM Level 2. Optional.
+ * Create and return Event objects.
+ *
+ * @param type The eventType parameter specifies the type of Event
+ * interface to be created. If the Event interface specified is supported
+ * by the implementation this method will return a new Event of the
+ * interface type requested. If the Event is to be dispatched via the
+ * dispatchEvent method the appropriate event init method must be called
+ * after creation in order to initialize the Event's values. As an
+ * example, a user wishing to synthesize some kind of Event would call
+ * createEvent with the parameter "Events". The initEvent method could then
+ * be called on the newly created Event to set the specific type of Event
+ * to be dispatched and set its context information.
+ * @return Newly created Event
+ * @exception DOMException NOT_SUPPORTED_ERR: Raised if the implementation
+ * does not support the type of Event interface requested
+ * @since WD-DOM-Level-2-19990923
+ */
+ public Event createEvent(String type) throws DOMException {
+ if (type.equalsIgnoreCase("Events") ||
+ "Event".equals(type)) {
+ return new EventImpl();
+ }
+ else if (type.equalsIgnoreCase("MutationEvents") ||
+ "MutationEvent".equals(type)) {
+ return new MutationEventImpl();
+ }
+ else if (type.equalsIgnoreCase("UIEvents") ||
+ "UIEvent".equals(type)) {
+ return new UIEventImpl();
+ }
+ else if (type.equalsIgnoreCase("MouseEvents") ||
+ "MouseEvent".equals(type)) {
+ return new MouseEventImpl();
+ }
+ else {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+ }
+
+ /**
+ * Sets whether the DOM implementation generates mutation events
+ * upon operations.
+ */
+ void setMutationEvents(boolean set) {
+ mutationEvents = set;
+ }
+
+ /**
+ * Returns true if the DOM implementation generates mutation events.
+ */
+ boolean getMutationEvents() {
+ return mutationEvents;
+ }
+
+ /**
+ * Store event listener registered on a given node
+ * This is another place where we could use weak references! Indeed, the
+ * node here won't be GC'ed as long as some listener is registered on it,
+ * since the eventsListeners table will have a reference to the node.
+ */
+ protected void setEventListeners(NodeImpl n, Vector listeners) {
+ if (eventListeners == null) {
+ eventListeners = new Hashtable();
+ }
+ if (listeners == null) {
+ eventListeners.remove(n);
+ if (eventListeners.isEmpty()) {
+ // stop firing events when there isn't any listener
+ mutationEvents = false;
+ }
+ } else {
+ eventListeners.put(n, listeners);
+ // turn mutation events on
+ mutationEvents = true;
+ }
+ }
+
+ /**
+ * Retreive event listener registered on a given node
+ */
+ protected Vector getEventListeners(NodeImpl n) {
+ if (eventListeners == null) {
+ return null;
+ }
+ return (Vector) eventListeners.get(n);
+ }
+
+ //
+ // EventTarget support (public and internal)
+ //
+
+ //
+ // Constants
+ //
+
+ /*
+ * NON-DOM INTERNAL: Class LEntry is just a struct used to represent
+ * event listeners registered with this node. Copies of this object
+ * are hung from the nodeListeners Vector.
+ *
+ * I considered using two vectors -- one for capture,
+ * one for bubble -- but decided that since the list of listeners
+ * is probably short in most cases, it might not be worth spending
+ * the space. ***** REVISIT WHEN WE HAVE MORE EXPERIENCE.
+ */
+ class LEntry implements Serializable {
+
+ private static final long serialVersionUID = -8426757059492421631L;
+ String type;
+ EventListener listener;
+ boolean useCapture;
+
+ /** NON-DOM INTERNAL: Constructor for Listener list Entry
+ * @param type Event name (NOT event group!) to listen for.
+ * @param listener Who gets called when event is dispatched
+ * @param useCaptue True iff listener is registered on
+ * capturing phase rather than at-target or bubbling
+ */
+ LEntry(String type, EventListener listener, boolean useCapture)
+ {
+ this.type = type;
+ this.listener = listener;
+ this.useCapture = useCapture;
+ }
+
+ } // LEntry
+
+ /**
+ * Introduced in DOM Level 2. Register an event listener with this
+ * Node. A listener may be independently registered as both Capturing and
+ * Bubbling, but may only be registered once per role; redundant
+ * registrations are ignored.
+ * @param node node to add listener to
+ * @param type Event name (NOT event group!) to listen for.
+ * @param listener Who gets called when event is dispatched
+ * @param useCapture True iff listener is registered on
+ * capturing phase rather than at-target or bubbling
+ */
+ protected void addEventListener(NodeImpl node, String type,
+ EventListener listener, boolean useCapture)
+ {
+ // We can't dispatch to blank type-name, and of course we need
+ // a listener to dispatch to
+ if (type == null || type.length() == 0 || listener == null)
+ return;
+
+ // Each listener may be registered only once per type per phase.
+ // Simplest way to code that is to zap the previous entry, if any.
+ removeEventListener(node, type, listener, useCapture);
+
+ Vector nodeListeners = getEventListeners(node);
+ if(nodeListeners == null) {
+ nodeListeners = new Vector();
+ setEventListeners(node, nodeListeners);
+ }
+ nodeListeners.addElement(new LEntry(type, listener, useCapture));
+
+ // Record active listener
+ LCount lc = LCount.lookup(type);
+ if (useCapture) {
+ ++lc.captures;
+ ++lc.total;
+ }
+ else {
+ ++lc.bubbles;
+ ++lc.total;
+ }
+
+ } // addEventListener(NodeImpl,String,EventListener,boolean) :void
+
+ /**
+ * Introduced in DOM Level 2. Deregister an event listener previously
+ * registered with this Node. A listener must be independently removed
+ * from the Capturing and Bubbling roles. Redundant removals (of listeners
+ * not currently registered for this role) are ignored.
+ * @param node node to remove listener from
+ * @param type Event name (NOT event group!) to listen for.
+ * @param listener Who gets called when event is dispatched
+ * @param useCapture True iff listener is registered on
+ * capturing phase rather than at-target or bubbling
+ */
+ protected void removeEventListener(NodeImpl node, String type,
+ EventListener listener,
+ boolean useCapture)
+ {
+ // If this couldn't be a valid listener registration, ignore request
+ if (type == null || type.length() == 0 || listener == null)
+ return;
+ Vector nodeListeners = getEventListeners(node);
+ if (nodeListeners == null)
+ return;
+
+ // Note that addListener has previously ensured that
+ // each listener may be registered only once per type per phase.
+ // count-down is OK for deletions!
+ for (int i = nodeListeners.size() - 1; i >= 0; --i) {
+ LEntry le = (LEntry) nodeListeners.elementAt(i);
+ if (le.useCapture == useCapture && le.listener == listener &&
+ le.type.equals(type)) {
+ nodeListeners.removeElementAt(i);
+ // Storage management: Discard empty listener lists
+ if (nodeListeners.size() == 0)
+ setEventListeners(node, null);
+
+ // Remove active listener
+ LCount lc = LCount.lookup(type);
+ if (useCapture) {
+ --lc.captures;
+ --lc.total;
+ }
+ else {
+ --lc.bubbles;
+ --lc.total;
+ }
+
+ break; // Found it; no need to loop farther.
+ }
+ }
+ } // removeEventListener(NodeImpl,String,EventListener,boolean) :void
+
+ protected void copyEventListeners(NodeImpl src, NodeImpl tgt) {
+ Vector nodeListeners = getEventListeners(src);
+ if (nodeListeners == null) {
+ return;
+ }
+ setEventListeners(tgt, (Vector) nodeListeners.clone());
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ * Distribution engine for DOM Level 2 Events.
+ *
+ * Event propagation runs as follows:
+ *
+ * - Event is dispatched to a particular target node, which invokes
+ * this code. Note that the event's stopPropagation flag is
+ * cleared when dispatch begins; thereafter, if it has
+ * been set before processing of a node commences, we instead
+ * immediately advance to the DEFAULT phase.
+ *
- The node's ancestors are established as destinations for events.
+ * For capture and bubble purposes, node ancestry is determined at
+ * the time dispatch starts. If an event handler alters the document
+ * tree, that does not change which nodes will be informed of the event.
+ *
- CAPTURING_PHASE: Ancestors are scanned, root to target, for
+ * Capturing listeners. If found, they are invoked (see below).
+ *
- AT_TARGET:
+ * Event is dispatched to NON-CAPTURING listeners on the
+ * target node. Note that capturing listeners on this node are _not_
+ * invoked.
+ *
- BUBBLING_PHASE: Ancestors are scanned, target to root, for
+ * non-capturing listeners.
+ *
- Default processing: Some DOMs have default behaviors bound to
+ * specific nodes. If this DOM does, and if the event's preventDefault
+ * flag has not been set, we now return to the target node and process
+ * its default handler for this event, if any.
+ *
+ *
+ * Note that registration of handlers during processing of an event does
+ * not take effect during this phase of this event; they will not be called
+ * until the next time this node is visited by dispatchEvent. On the other
+ * hand, removals take effect immediately.
+ *
+ * If an event handler itself causes events to be dispatched, they are
+ * processed synchronously, before processing resumes
+ * on the event which triggered them. Please be aware that this may
+ * result in events arriving at listeners "out of order" relative
+ * to the actual sequence of requests.
+ *
+ * Note that our implementation resets the event's stop/prevent flags
+ * when dispatch begins.
+ * I believe the DOM's intent is that event objects be redispatchable,
+ * though it isn't stated in those terms.
+ * @param node node to dispatch to
+ * @param event the event object to be dispatched to
+ * registered EventListeners
+ * @return true if the event's preventDefault()
+ * method was invoked by an EventListener; otherwise false.
+ */
+ protected boolean dispatchEvent(NodeImpl node, Event event) {
+ if (event == null) return false;
+
+ // Can't use anyone else's implementation, since there's no public
+ // API for setting the event's processing-state fields.
+ EventImpl evt = (EventImpl)event;
+
+ // VALIDATE -- must have been initialized at least once, must have
+ // a non-null non-blank name.
+ if (!evt.initialized || evt.type == null || evt.type.length() == 0) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "UNSPECIFIED_EVENT_TYPE_ERR", null);
+ throw new EventException(EventException.UNSPECIFIED_EVENT_TYPE_ERR, msg);
+ }
+
+ // If nobody is listening for this event, discard immediately
+ LCount lc = LCount.lookup(evt.getType());
+ if (lc.total == 0)
+ return evt.preventDefault;
+
+ // INITIALIZE THE EVENT'S DISPATCH STATUS
+ // (Note that Event objects are reusable in our implementation;
+ // that doesn't seem to be explicitly guaranteed in the DOM, but
+ // I believe it is the intent.)
+ evt.target = node;
+ evt.stopPropagation = false;
+ evt.preventDefault = false;
+
+ // Capture pre-event parentage chain, not including target;
+ // use pre-event-dispatch ancestors even if event handlers mutate
+ // document and change the target's context.
+ // Note that this is parents ONLY; events do not
+ // cross the Attr/Element "blood/brain barrier".
+ // DOMAttrModified. which looks like an exception,
+ // is issued to the Element rather than the Attr
+ // and causes a _second_ DOMSubtreeModified in the Element's
+ // tree.
+ ArrayList pv = new ArrayList(10);
+ Node p = node;
+ Node n = p.getParentNode();
+ while (n != null) {
+ pv.add(n);
+ p = n;
+ n = n.getParentNode();
+ }
+
+ // CAPTURING_PHASE:
+ if (lc.captures > 0) {
+ evt.eventPhase = Event.CAPTURING_PHASE;
+ // Ancestors are scanned, root to target, for
+ // Capturing listeners.
+ for (int j = pv.size() - 1; j >= 0; --j) {
+ if (evt.stopPropagation)
+ break; // Someone set the flag. Phase ends.
+
+ // Handle all capturing listeners on this node
+ NodeImpl nn = (NodeImpl) pv.get(j);
+ evt.currentTarget = nn;
+ Vector nodeListeners = getEventListeners(nn);
+ if (nodeListeners != null) {
+ Vector nl = (Vector) nodeListeners.clone();
+ // call listeners in the order in which they got registered
+ int nlsize = nl.size();
+ for (int i = 0; i < nlsize; i++) {
+ LEntry le = (LEntry) nl.elementAt(i);
+ if (le.useCapture && le.type.equals(evt.type) &&
+ nodeListeners.contains(le)) {
+ try {
+ le.listener.handleEvent(evt);
+ }
+ catch (Exception e) {
+ // All exceptions are ignored.
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ // Both AT_TARGET and BUBBLE use non-capturing listeners.
+ if (lc.bubbles > 0) {
+ // AT_TARGET PHASE: Event is dispatched to NON-CAPTURING listeners
+ // on the target node. Note that capturing listeners on the target
+ // node are _not_ invoked, even during the capture phase.
+ evt.eventPhase = Event.AT_TARGET;
+ evt.currentTarget = node;
+ Vector nodeListeners = getEventListeners(node);
+ if (!evt.stopPropagation && nodeListeners != null) {
+ Vector nl = (Vector) nodeListeners.clone();
+ // call listeners in the order in which they got registered
+ int nlsize = nl.size();
+ for (int i = 0; i < nlsize; i++) {
+ LEntry le = (LEntry) nl.elementAt(i);
+ if (!le.useCapture && le.type.equals(evt.type) &&
+ nodeListeners.contains(le)) {
+ try {
+ le.listener.handleEvent(evt);
+ }
+ catch (Exception e) {
+ // All exceptions are ignored.
+ }
+ }
+ }
+ }
+ // BUBBLING_PHASE: Ancestors are scanned, target to root, for
+ // non-capturing listeners. If the event's preventBubbling flag
+ // has been set before processing of a node commences, we
+ // instead immediately advance to the default phase.
+ // Note that not all events bubble.
+ if (evt.bubbles) {
+ evt.eventPhase = Event.BUBBLING_PHASE;
+ int pvsize = pv.size();
+ for (int j = 0; j < pvsize; j++) {
+ if (evt.stopPropagation)
+ break; // Someone set the flag. Phase ends.
+
+ // Handle all bubbling listeners on this node
+ NodeImpl nn = (NodeImpl) pv.get(j);
+ evt.currentTarget = nn;
+ nodeListeners = getEventListeners(nn);
+ if (nodeListeners != null) {
+ Vector nl = (Vector) nodeListeners.clone();
+ // call listeners in the order in which they got
+ // registered
+ int nlsize = nl.size();
+ for (int i = 0; i < nlsize; i++) {
+ LEntry le = (LEntry) nl.elementAt(i);
+ if (!le.useCapture && le.type.equals(evt.type) &&
+ nodeListeners.contains(le)) {
+ try {
+ le.listener.handleEvent(evt);
+ }
+ catch (Exception e) {
+ // All exceptions are ignored.
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // DEFAULT PHASE: Some DOMs have default behaviors bound to specific
+ // nodes. If this DOM does, and if the event's preventDefault flag has
+ // not been set, we now return to the target node and process its
+ // default handler for this event, if any.
+ // No specific phase value defined, since this is DOM-internal
+ if (lc.defaults > 0 && (!evt.cancelable || !evt.preventDefault)) {
+ // evt.eventPhase = Event.DEFAULT_PHASE;
+ // evt.currentTarget = node;
+ // DO_DEFAULT_OPERATION
+ }
+
+ return evt.preventDefault;
+ } // dispatchEvent(NodeImpl,Event) :boolean
+
+ /**
+ * NON-DOM INTERNAL: DOMNodeInsertedIntoDocument and ...RemovedFrom...
+ * are dispatched to an entire subtree. This is the distribution code
+ * therefor. They DO NOT bubble, thanks be, but may be captured.
+ *
+ * Similar to code in dispatchingEventToSubtree however this method
+ * is only used on the target node and does not start a dispatching chain
+ * on the sibling of the target node as this is not part of the subtree
+ * ***** At the moment I'm being sloppy and using the normal
+ * capture dispatcher on every node. This could be optimized hugely
+ * by writing a capture engine that tracks our position in the tree to
+ * update the capture chain without repeated chases up to root.
+ * @param n target node (that was directly inserted or removed)
+ * @param e event to be sent to that node and its subtree
+ */
+ protected void dispatchEventToSubtree(Node n, Event e) {
+
+ ((NodeImpl) n).dispatchEvent(e);
+ if (n.getNodeType() == Node.ELEMENT_NODE) {
+ NamedNodeMap a = n.getAttributes();
+ for (int i = a.getLength() - 1; i >= 0; --i)
+ dispatchingEventToSubtree(a.item(i), e);
+ }
+ dispatchingEventToSubtree(n.getFirstChild(), e);
+
+ } // dispatchEventToSubtree(NodeImpl,Node,Event) :void
+
+
+ /**
+ * Dispatches event to the target node's descendents recursively
+ *
+ * @param n node to dispatch to
+ * @param e event to be sent to that node and its subtree
+ */
+ protected void dispatchingEventToSubtree(Node n, Event e) {
+ if (n==null)
+ return;
+
+ // ***** Recursive implementation. This is excessively expensive,
+ // and should be replaced in conjunction with optimization
+ // mentioned above.
+ ((NodeImpl) n).dispatchEvent(e);
+ if (n.getNodeType() == Node.ELEMENT_NODE) {
+ NamedNodeMap a = n.getAttributes();
+ for (int i = a.getLength() - 1; i >= 0; --i)
+ dispatchingEventToSubtree(a.item(i), e);
+ }
+ dispatchingEventToSubtree(n.getFirstChild(), e);
+ dispatchingEventToSubtree(n.getNextSibling(), e);
+ }
+
+ /**
+ * NON-DOM INTERNAL: Return object for getEnclosingAttr. Carries
+ * (two values, the Attr node affected (if any) and its previous
+ * string value. Simple struct, no methods.
+ */
+ class EnclosingAttr implements Serializable {
+ private static final long serialVersionUID = 5208387723391647216L;
+ AttrImpl node;
+ String oldvalue;
+ }
+
+ EnclosingAttr savedEnclosingAttr;
+
+ /**
+ * NON-DOM INTERNAL: Convenience wrapper for calling
+ * dispatchAggregateEvents when the context was established
+ * by savedEnclosingAttr .
+ * @param node node to dispatch to
+ * @param ea description of Attr affected by current operation
+ */
+ protected void dispatchAggregateEvents(NodeImpl node, EnclosingAttr ea) {
+ if (ea != null)
+ dispatchAggregateEvents(node, ea.node, ea.oldvalue,
+ MutationEvent.MODIFICATION);
+ else
+ dispatchAggregateEvents(node, null, null, (short) 0);
+
+ } // dispatchAggregateEvents(NodeImpl,EnclosingAttr) :void
+
+ /**
+ * NON-DOM INTERNAL: Generate the "aggregated" post-mutation events
+ * DOMAttrModified and DOMSubtreeModified.
+ * Both of these should be issued only once for each user-requested
+ * mutation operation, even if that involves multiple changes to
+ * the DOM.
+ * For example, if a DOM operation makes multiple changes to a single
+ * Attr before returning, it would be nice to generate only one
+ * DOMAttrModified, and multiple changes over larger scope but within
+ * a recognizable single subtree might want to generate only one
+ * DOMSubtreeModified, sent to their lowest common ancestor.
+ *
+ * To manage this, use the "internal" versions of insert and remove
+ * with MUTATION_LOCAL, then make an explicit call to this routine
+ * at the higher level. Some examples now exist in our code.
+ *
+ * @param node The node to dispatch to
+ * @param enclosingAttr The Attr node (if any) whose value has been changed
+ * as a result of the DOM operation. Null if none such.
+ * @param oldvalue The String value previously held by the
+ * enclosingAttr. Ignored if none such.
+ * @param change Type of modification to the attr. See
+ * MutationEvent.attrChange
+ */
+ protected void dispatchAggregateEvents(NodeImpl node,
+ AttrImpl enclosingAttr,
+ String oldvalue, short change) {
+ // We have to send DOMAttrModified.
+ NodeImpl owner = null;
+ if (enclosingAttr != null) {
+ LCount lc = LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
+ owner = (NodeImpl) enclosingAttr.getOwnerElement();
+ if (lc.total > 0) {
+ if (owner != null) {
+ MutationEventImpl me = new MutationEventImpl();
+ me.initMutationEvent(MutationEventImpl.DOM_ATTR_MODIFIED,
+ true, false, enclosingAttr,
+ oldvalue,
+ enclosingAttr.getNodeValue(),
+ enclosingAttr.getNodeName(),
+ change);
+ owner.dispatchEvent(me);
+ }
+ }
+ }
+ // DOMSubtreeModified gets sent to the lowest common root of a
+ // set of changes.
+ // "This event is dispatched after all other events caused by the
+ // mutation have been fired."
+ LCount lc = LCount.lookup(MutationEventImpl.DOM_SUBTREE_MODIFIED);
+ if (lc.total > 0) {
+ MutationEvent me = new MutationEventImpl();
+ me.initMutationEvent(MutationEventImpl.DOM_SUBTREE_MODIFIED,
+ true, false, null, null,
+ null, null, (short) 0);
+
+ // If we're within an Attr, DStM gets sent to the Attr
+ // and to its owningElement. Otherwise we dispatch it
+ // locally.
+ if (enclosingAttr != null) {
+ dispatchEvent(enclosingAttr, me);
+ if (owner != null)
+ dispatchEvent(owner, me);
+ }
+ else
+ dispatchEvent(node, me);
+ }
+ } // dispatchAggregateEvents(NodeImpl, AttrImpl,String) :void
+
+ /**
+ * NON-DOM INTERNAL: Pre-mutation context check, in
+ * preparation for later generating DOMAttrModified events.
+ * Determines whether this node is within an Attr
+ * @param node node to get enclosing attribute for
+ */
+ protected void saveEnclosingAttr(NodeImpl node) {
+ savedEnclosingAttr = null;
+ // MUTATION PREPROCESSING AND PRE-EVENTS:
+ // If we're within the scope of an Attr and DOMAttrModified
+ // was requested, we need to preserve its previous value for
+ // that event.
+ LCount lc = LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
+ if (lc.total > 0) {
+ NodeImpl eventAncestor = node;
+ while (true) {
+ if (eventAncestor == null)
+ return;
+ int type = eventAncestor.getNodeType();
+ if (type == Node.ATTRIBUTE_NODE) {
+ EnclosingAttr retval = new EnclosingAttr();
+ retval.node = (AttrImpl) eventAncestor;
+ retval.oldvalue = retval.node.getNodeValue();
+ savedEnclosingAttr = retval;
+ return;
+ }
+ else if (type == Node.ENTITY_REFERENCE_NODE)
+ eventAncestor = eventAncestor.parentNode();
+ else if (type == Node.TEXT_NODE)
+ eventAncestor = eventAncestor.parentNode();
+ else
+ return;
+ // Any other parent means we're not in an Attr
+ }
+ }
+ } // saveEnclosingAttr(NodeImpl) :void
+
+ /**
+ * A method to be called when a character data node has been modified
+ */
+ void modifyingCharacterData(NodeImpl node, boolean replace) {
+ if (mutationEvents) {
+ if (!replace) {
+ saveEnclosingAttr(node);
+ }
+ }
+ }
+
+ /**
+ * A method to be called when a character data node has been modified
+ */
+ void modifiedCharacterData(NodeImpl node, String oldvalue, String value, boolean replace) {
+ if (mutationEvents) {
+ mutationEventsModifiedCharacterData(node, oldvalue, value, replace);
+ }
+ }
+
+ private void mutationEventsModifiedCharacterData(NodeImpl node, String oldvalue, String value, boolean replace) {
+ if (!replace) {
+ // MUTATION POST-EVENTS:
+ LCount lc =
+ LCount.lookup(MutationEventImpl.DOM_CHARACTER_DATA_MODIFIED);
+ if (lc.total > 0) {
+ MutationEvent me = new MutationEventImpl();
+ me.initMutationEvent(
+ MutationEventImpl.DOM_CHARACTER_DATA_MODIFIED,
+ true, false, null,
+ oldvalue, value, null, (short) 0);
+ dispatchEvent(node, me);
+ }
+
+ // Subroutine: Transmit DOMAttrModified and DOMSubtreeModified,
+ // if required. (Common to most kinds of mutation)
+ dispatchAggregateEvents(node, savedEnclosingAttr);
+ } // End mutation postprocessing
+ }
+
+ /**
+ * A method to be called when a character data node has been replaced
+ */
+ void replacedCharacterData(NodeImpl node, String oldvalue, String value) {
+ //now that we have finished replacing data, we need to perform the same actions
+ //that are required after a character data node has been modified
+ //send the value of false for replace parameter so that mutation
+ //events if appropriate will be initiated
+ modifiedCharacterData(node, oldvalue, value, false);
+ }
+
+ /**
+ * A method to be called when a node is about to be inserted in the tree.
+ */
+ void insertingNode(NodeImpl node, boolean replace) {
+ if (mutationEvents) {
+ if (!replace) {
+ saveEnclosingAttr(node);
+ }
+ }
+ }
+
+ /**
+ * A method to be called when a node has been inserted in the tree.
+ */
+ void insertedNode(NodeImpl node, NodeImpl newInternal, boolean replace) {
+ if (mutationEvents) {
+ mutationEventsInsertedNode(node, newInternal, replace);
+ }
+
+ // notify the range of insertions
+ if (ranges != null) {
+ notifyRangesInsertedNode(newInternal);
+ }
+ }
+
+ private void mutationEventsInsertedNode(NodeImpl node, NodeImpl newInternal, boolean replace) {
+ // MUTATION POST-EVENTS:
+ // "Local" events (non-aggregated)
+ // New child is told it was inserted, and where
+ LCount lc = LCount.lookup(MutationEventImpl.DOM_NODE_INSERTED);
+ if (lc.total > 0) {
+ MutationEventImpl me = new MutationEventImpl();
+ me.initMutationEvent(MutationEventImpl.DOM_NODE_INSERTED,
+ true, false, node,
+ null, null, null, (short) 0);
+ dispatchEvent(newInternal, me);
+ }
+
+ // If within the Document, tell the subtree it's been added
+ // to the Doc.
+ lc = LCount.lookup(
+ MutationEventImpl.DOM_NODE_INSERTED_INTO_DOCUMENT);
+ if (lc.total > 0) {
+ NodeImpl eventAncestor = node;
+ if (savedEnclosingAttr != null)
+ eventAncestor = (NodeImpl)
+ savedEnclosingAttr.node.getOwnerElement();
+ if (eventAncestor != null) { // Might have been orphan Attr
+ NodeImpl p = eventAncestor;
+ while (p != null) {
+ eventAncestor = p; // Last non-null ancestor
+ // In this context, ancestry includes
+ // walking back from Attr to Element
+ if (p.getNodeType() == ATTRIBUTE_NODE) {
+ p = (NodeImpl) ((AttrImpl)p).getOwnerElement();
+ }
+ else {
+ p = p.parentNode();
+ }
+ }
+ if (eventAncestor.getNodeType() == Node.DOCUMENT_NODE){
+ MutationEventImpl me = new MutationEventImpl();
+ me.initMutationEvent(MutationEventImpl
+ .DOM_NODE_INSERTED_INTO_DOCUMENT,
+ false,false,null,null,
+ null,null,(short)0);
+ dispatchEventToSubtree(newInternal, me);
+ }
+ }
+ }
+ if (!replace) {
+ // Subroutine: Transmit DOMAttrModified and DOMSubtreeModified
+ // (Common to most kinds of mutation)
+ dispatchAggregateEvents(node, savedEnclosingAttr);
+ }
+ }
+
+ private void notifyRangesInsertedNode(NodeImpl newInternal) {
+ removeStaleRangeReferences();
+ final Iterator i = ranges.iterator();
+ while (i.hasNext()) {
+ RangeImpl range = (RangeImpl) ((Reference) i.next()).get();
+ if (range != null) {
+ range.insertedNodeFromDOM(newInternal);
+ }
+ // Remove stale reference from the list.
+ else {
+ i.remove();
+ }
+ }
+ }
+
+ /**
+ * A method to be called when a node is about to be removed from the tree.
+ */
+ void removingNode(NodeImpl node, NodeImpl oldChild, boolean replace) {
+
+ // notify iterators
+ if (iterators != null) {
+ notifyIteratorsRemovingNode(oldChild);
+ }
+
+ // notify ranges
+ if (ranges != null) {
+ notifyRangesRemovingNode(oldChild);
+ }
+
+ // mutation events
+ if (mutationEvents) {
+ mutationEventsRemovingNode(node, oldChild, replace);
+ }
+ }
+
+ private void notifyIteratorsRemovingNode(NodeImpl oldChild) {
+ removeStaleIteratorReferences();
+ final Iterator i = iterators.iterator();
+ while (i.hasNext()) {
+ NodeIteratorImpl iterator = (NodeIteratorImpl) ((Reference) i.next()).get();
+ if (iterator != null) {
+ iterator.removeNode(oldChild);
+ }
+ // Remove stale reference from the list.
+ else {
+ i.remove();
+ }
+ }
+ }
+
+ private void notifyRangesRemovingNode(NodeImpl oldChild) {
+ removeStaleRangeReferences();
+ final Iterator i = ranges.iterator();
+ while (i.hasNext()) {
+ RangeImpl range = (RangeImpl) ((Reference) i.next()).get();
+ if (range != null) {
+ range.removeNode(oldChild);
+ }
+ // Remove stale reference from the list.
+ else {
+ i.remove();
+ }
+ }
+ }
+
+ private void mutationEventsRemovingNode(NodeImpl node, NodeImpl oldChild, boolean replace) {
+ // MUTATION PREPROCESSING AND PRE-EVENTS:
+ // If we're within the scope of an Attr and DOMAttrModified
+ // was requested, we need to preserve its previous value for
+ // that event.
+ if (!replace) {
+ saveEnclosingAttr(node);
+ }
+ // Child is told that it is about to be removed
+ LCount lc = LCount.lookup(MutationEventImpl.DOM_NODE_REMOVED);
+ if (lc.total > 0) {
+ MutationEventImpl me= new MutationEventImpl();
+ me.initMutationEvent(MutationEventImpl.DOM_NODE_REMOVED,
+ true, false, node, null,
+ null, null, (short) 0);
+ dispatchEvent(oldChild, me);
+ }
+
+ // If within Document, child's subtree is informed that it's
+ // losing that status
+ lc = LCount.lookup(
+ MutationEventImpl.DOM_NODE_REMOVED_FROM_DOCUMENT);
+ if (lc.total > 0) {
+ NodeImpl eventAncestor = this;
+ if(savedEnclosingAttr != null)
+ eventAncestor = (NodeImpl)
+ savedEnclosingAttr.node.getOwnerElement();
+ if (eventAncestor != null) { // Might have been orphan Attr
+ for (NodeImpl p = eventAncestor.parentNode();
+ p != null; p = p.parentNode()) {
+ eventAncestor = p; // Last non-null ancestor
+ }
+ if (eventAncestor.getNodeType() == Node.DOCUMENT_NODE){
+ MutationEventImpl me = new MutationEventImpl();
+ me.initMutationEvent(
+ MutationEventImpl.DOM_NODE_REMOVED_FROM_DOCUMENT,
+ false, false, null,
+ null, null, null, (short) 0);
+ dispatchEventToSubtree(oldChild, me);
+ }
+ }
+ }
+ // End mutation preprocessing
+ }
+
+ /**
+ * A method to be called when a node has been removed from the tree.
+ */
+ void removedNode(NodeImpl node, boolean replace) {
+ if (mutationEvents) {
+ // MUTATION POST-EVENTS:
+ // Subroutine: Transmit DOMAttrModified and DOMSubtreeModified,
+ // if required. (Common to most kinds of mutation)
+ if (!replace) {
+ dispatchAggregateEvents(node, savedEnclosingAttr);
+ }
+ } // End mutation postprocessing
+ }
+
+ /**
+ * A method to be called when a node is about to be replaced in the tree.
+ */
+ void replacingNode(NodeImpl node) {
+ if (mutationEvents) {
+ saveEnclosingAttr(node);
+ }
+ }
+
+ /**
+ * A method to be called when character data is about to be replaced in the tree.
+ */
+ void replacingData (NodeImpl node) {
+ if (mutationEvents) {
+ saveEnclosingAttr(node);
+ }
+ }
+
+ /**
+ * A method to be called when a node has been replaced in the tree.
+ */
+ void replacedNode(NodeImpl node) {
+ if (mutationEvents) {
+ dispatchAggregateEvents(node, savedEnclosingAttr);
+ }
+ }
+
+ /**
+ * A method to be called when an attribute value has been modified
+ */
+ void modifiedAttrValue(AttrImpl attr, String oldvalue) {
+ if (mutationEvents) {
+ // MUTATION POST-EVENTS:
+ dispatchAggregateEvents(attr, attr, oldvalue,
+ MutationEvent.MODIFICATION);
+ }
+ }
+
+ /**
+ * A method to be called when an attribute node has been set
+ */
+ void setAttrNode(AttrImpl attr, AttrImpl previous) {
+ if (mutationEvents) {
+ // MUTATION POST-EVENTS:
+ if (previous == null) {
+ dispatchAggregateEvents(attr.ownerNode, attr, null,
+ MutationEvent.ADDITION);
+ }
+ else {
+ dispatchAggregateEvents(attr.ownerNode, attr,
+ previous.getNodeValue(),
+ MutationEvent.MODIFICATION);
+ }
+ }
+ }
+
+ /**
+ * A method to be called when an attribute node has been removed
+ */
+ void removedAttrNode(AttrImpl attr, NodeImpl oldOwner, String name) {
+ // We can't use the standard dispatchAggregate, since it assumes
+ // that the Attr is still attached to an owner. This code is
+ // similar but dispatches to the previous owner, "element".
+ if (mutationEvents) {
+ mutationEventsRemovedAttrNode(attr, oldOwner, name);
+ }
+ }
+
+ private void mutationEventsRemovedAttrNode(AttrImpl attr, NodeImpl oldOwner, String name) {
+ // If we have to send DOMAttrModified (determined earlier),
+ // do so.
+ LCount lc = LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
+ if (lc.total > 0) {
+ MutationEventImpl me= new MutationEventImpl();
+ me.initMutationEvent(MutationEventImpl.DOM_ATTR_MODIFIED,
+ true, false, attr,
+ attr.getNodeValue(), null, name,
+ MutationEvent.REMOVAL);
+ dispatchEvent(oldOwner, me);
+ }
+
+ // We can hand off to process DOMSubtreeModified, though.
+ // Note that only the Element needs to be informed; the
+ // Attr's subtree has not been changed by this operation.
+ dispatchAggregateEvents(oldOwner, null, null, (short) 0);
+ }
+
+ /**
+ * A method to be called when an attribute node has been renamed
+ */
+ void renamedAttrNode(Attr oldAt, Attr newAt) {
+ // REVISIT: To be implemented!!!
+ }
+
+ /**
+ * A method to be called when an element has been renamed
+ */
+ void renamedElement(Element oldEl, Element newEl) {
+ // REVISIT: To be implemented!!!
+ }
+
+} // class DocumentImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/DocumentTypeImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/DocumentTypeImpl.java
new file mode 100644
index 0000000..4f33644
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/DocumentTypeImpl.java
@@ -0,0 +1,484 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.util.Hashtable;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.UserDataHandler;
+
+/**
+ * This class represents a Document Type declaraction in
+ * the document itself, not a Document Type Definition (DTD).
+ * An XML document may (or may not) have such a reference.
+ *
+ * DocumentType is an Extended DOM feature, used in XML documents but
+ * not in HTML.
+ *
+ * Note that Entities and Notations are no longer children of the
+ * DocumentType, but are parentless nodes hung only in their
+ * appropriate NamedNodeMaps.
+ *
+ * This area is UNDERSPECIFIED IN REC-DOM-Level-1-19981001
+ * Most notably, absolutely no provision was made for storing
+ * and using Element and Attribute information. Nor was the linkage
+ * between Entities and Entity References nailed down solidly.
+ *
+ * @xerces.internal
+ *
+ * @author Arnaud Le Hors, IBM
+ * @author Joe Kesselman, IBM
+ * @author Andy Clark, IBM
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class DocumentTypeImpl
+ extends ParentNode
+ implements DocumentType {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 7751299192316526485L;
+
+ //
+ // Data
+ //
+
+ /** Document type name. */
+ protected String name;
+
+ /** Entities. */
+ protected NamedNodeMapImpl entities;
+
+ /** Notations. */
+ protected NamedNodeMapImpl notations;
+
+ // NON-DOM
+
+ /** Elements. */
+ protected NamedNodeMapImpl elements;
+
+ // DOM2: support public ID.
+ protected String publicID;
+
+ // DOM2: support system ID.
+ protected String systemID;
+
+ // DOM2: support internal subset.
+ protected String internalSubset;
+
+ /** The following are required for compareDocumentPosition
+ */
+ // Doctype number. Doc types which have no owner may be assigned
+ // a number, on demand, for ordering purposes for compareDocumentPosition
+ private int doctypeNumber=0;
+
+ //
+ // Constructors
+ //
+ private Hashtable userData = null;
+ /** Factory method for creating a document type node. */
+ public DocumentTypeImpl(CoreDocumentImpl ownerDocument, String name) {
+ super(ownerDocument);
+
+ this.name = name;
+ // DOM
+ entities = new NamedNodeMapImpl(this);
+ notations = new NamedNodeMapImpl(this);
+
+ // NON-DOM
+ elements = new NamedNodeMapImpl(this);
+
+ } // (CoreDocumentImpl,String)
+
+ /** Factory method for creating a document type node. */
+ public DocumentTypeImpl(CoreDocumentImpl ownerDocument,
+ String qualifiedName,
+ String publicID, String systemID) {
+ this(ownerDocument, qualifiedName);
+ this.publicID = publicID;
+ this.systemID = systemID;
+
+ } // (CoreDocumentImpl,String)
+
+ //
+ // DOM2: methods.
+ //
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Return the public identifier of this Document type.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public String getPublicId() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return publicID;
+ }
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Return the system identifier of this Document type.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public String getSystemId() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return systemID;
+ }
+
+ /**
+ * NON-DOM.
+ *
+ * Set the internalSubset given as a string.
+ */
+ public void setInternalSubset(String internalSubset) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ this.internalSubset = internalSubset;
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Return the internalSubset given as a string.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public String getInternalSubset() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return internalSubset;
+ }
+
+ //
+ // Node methods
+ //
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public short getNodeType() {
+ return Node.DOCUMENT_TYPE_NODE;
+ }
+
+ /**
+ * Returns the document type name
+ */
+ public String getNodeName() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return name;
+ }
+
+ /** Clones the node. */
+ public Node cloneNode(boolean deep) {
+
+ DocumentTypeImpl newnode = (DocumentTypeImpl)super.cloneNode(deep);
+ // NamedNodeMaps must be cloned explicitly, to avoid sharing them.
+ newnode.entities = entities.cloneMap(newnode);
+ newnode.notations = notations.cloneMap(newnode);
+ newnode.elements = elements.cloneMap(newnode);
+
+ return newnode;
+
+ } // cloneNode(boolean):Node
+
+ /*
+ * Get Node text content
+ * @since DOM Level 3
+ */
+ public String getTextContent() throws DOMException {
+ return null;
+ }
+
+ /*
+ * Set Node text content
+ * @since DOM Level 3
+ */
+ public void setTextContent(String textContent)
+ throws DOMException {
+ // no-op
+ }
+
+ /**
+ * DOM Level 3 WD- Experimental.
+ * Override inherited behavior from ParentNodeImpl to support deep equal.
+ */
+ public boolean isEqualNode(Node arg) {
+
+ if (!super.isEqualNode(arg)) {
+ return false;
+ }
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ DocumentTypeImpl argDocType = (DocumentTypeImpl) arg;
+
+ //test if the following string attributes are equal: publicId,
+ //systemId, internalSubset.
+ if ((getPublicId() == null && argDocType.getPublicId() != null)
+ || (getPublicId() != null && argDocType.getPublicId() == null)
+ || (getSystemId() == null && argDocType.getSystemId() != null)
+ || (getSystemId() != null && argDocType.getSystemId() == null)
+ || (getInternalSubset() == null
+ && argDocType.getInternalSubset() != null)
+ || (getInternalSubset() != null
+ && argDocType.getInternalSubset() == null)) {
+ return false;
+ }
+
+ if (getPublicId() != null) {
+ if (!getPublicId().equals(argDocType.getPublicId())) {
+ return false;
+ }
+ }
+
+ if (getSystemId() != null) {
+ if (!getSystemId().equals(argDocType.getSystemId())) {
+ return false;
+ }
+ }
+
+ if (getInternalSubset() != null) {
+ if (!getInternalSubset().equals(argDocType.getInternalSubset())) {
+ return false;
+ }
+ }
+
+ //test if NamedNodeMaps entities and notations are equal
+ NamedNodeMapImpl argEntities = argDocType.entities;
+
+ if ((entities == null && argEntities != null)
+ || (entities != null && argEntities == null))
+ return false;
+
+ if (entities != null && argEntities != null) {
+ if (entities.getLength() != argEntities.getLength())
+ return false;
+
+ for (int index = 0; entities.item(index) != null; index++) {
+ Node entNode1 = entities.item(index);
+ Node entNode2 =
+ argEntities.getNamedItem(entNode1.getNodeName());
+
+ if (!((NodeImpl) entNode1).isEqualNode(entNode2))
+ return false;
+ }
+ }
+
+ NamedNodeMapImpl argNotations = argDocType.notations;
+
+ if ((notations == null && argNotations != null)
+ || (notations != null && argNotations == null))
+ return false;
+
+ if (notations != null && argNotations != null) {
+ if (notations.getLength() != argNotations.getLength())
+ return false;
+
+ for (int index = 0; notations.item(index) != null; index++) {
+ Node noteNode1 = notations.item(index);
+ Node noteNode2 =
+ argNotations.getNamedItem(noteNode1.getNodeName());
+
+ if (!((NodeImpl) noteNode1).isEqualNode(noteNode2))
+ return false;
+ }
+ }
+
+ return true;
+ } //end isEqualNode
+
+
+ /**
+ * NON-DOM
+ * set the ownerDocument of this node and its children
+ */
+ protected void setOwnerDocument(CoreDocumentImpl doc) {
+ super.setOwnerDocument(doc);
+ entities.setOwnerDocument(doc);
+ notations.setOwnerDocument(doc);
+ elements.setOwnerDocument(doc);
+ }
+
+ /** NON-DOM
+ Get the number associated with this doctype.
+ */
+ protected int getNodeNumber() {
+ // If the doctype has a document owner, get the node number
+ // relative to the owner doc
+ if (getOwnerDocument()!=null)
+ return super.getNodeNumber();
+
+ // The doctype is disconnected and not associated with any document.
+ // Assign the doctype a number relative to the implementation.
+ if (doctypeNumber==0) {
+
+ CoreDOMImplementationImpl cd = (CoreDOMImplementationImpl)CoreDOMImplementationImpl.getDOMImplementation();
+ doctypeNumber = cd.assignDocTypeNumber();
+ }
+ return doctypeNumber;
+ }
+
+ //
+ // DocumentType methods
+ //
+
+ /**
+ * Name of this document type. If we loaded from a DTD, this should
+ * be the name immediately following the DOCTYPE keyword.
+ */
+ public String getName() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return name;
+
+ } // getName():String
+
+ /**
+ * Access the collection of general Entities, both external and
+ * internal, defined in the DTD. For example, in:
+ *
+ *
+ * <!doctype example SYSTEM "ex.dtd" [
+ * <!ENTITY foo "foo">
+ * <!ENTITY bar "bar">
+ * <!ENTITY % baz "baz">
+ * ]>
+ *
+ *
+ * The Entities map includes foo and bar, but not baz. It is promised that
+ * only Nodes which are Entities will exist in this NamedNodeMap.
+ *
+ * For HTML, this will always be null.
+ *
+ * Note that "built in" entities such as & and < should be
+ * converted to their actual characters before being placed in the DOM's
+ * contained text, and should be converted back when the DOM is rendered
+ * as XML or HTML, and hence DO NOT appear here.
+ */
+ public NamedNodeMap getEntities() {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return entities;
+ }
+
+ /**
+ * Access the collection of Notations defined in the DTD. A
+ * notation declares, by name, the format of an XML unparsed entity
+ * or is used to formally declare a Processing Instruction target.
+ */
+ public NamedNodeMap getNotations() {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return notations;
+ }
+
+ //
+ // Public methods
+ //
+
+ /**
+ * NON-DOM: Subclassed to flip the entities' and notations' readonly switch
+ * as well.
+ * @see NodeImpl#setReadOnly
+ */
+ public void setReadOnly(boolean readOnly, boolean deep) {
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ super.setReadOnly(readOnly, deep);
+
+ // set read-only property
+ elements.setReadOnly(readOnly, true);
+ entities.setReadOnly(readOnly, true);
+ notations.setReadOnly(readOnly, true);
+
+ } // setReadOnly(boolean,boolean)
+
+ /**
+ * NON-DOM: Access the collection of ElementDefinitions.
+ * @see ElementDefinitionImpl
+ */
+ public NamedNodeMap getElements() {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return elements;
+ }
+
+ public Object setUserData(String key,
+ Object data, UserDataHandler handler) {
+ if(userData == null)
+ userData = new Hashtable();
+ if (data == null) {
+ if (userData != null) {
+ Object o = userData.remove(key);
+ if (o != null) {
+ UserDataRecord r = (UserDataRecord) o;
+ return r.fData;
+ }
+ }
+ return null;
+ }
+ else {
+ Object o = userData.put(key, new UserDataRecord(data, handler));
+ if (o != null) {
+ UserDataRecord r = (UserDataRecord) o;
+ return r.fData;
+ }
+ }
+ return null;
+ }
+
+ public Object getUserData(String key) {
+ if (userData == null) {
+ return null;
+ }
+ Object o = userData.get(key);
+ if (o != null) {
+ UserDataRecord r = (UserDataRecord) o;
+ return r.fData;
+ }
+ return null;
+ }
+
+ protected Hashtable getUserDataRecord(){
+ return userData;
+ }
+
+} // class DocumentTypeImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/ElementDefinitionImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/ElementDefinitionImpl.java
new file mode 100644
index 0000000..fc75136
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/ElementDefinitionImpl.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * NON-DOM CLASS: Describe one of the Elements (and its associated
+ * Attributes) defined in this Document Type.
+ *
+ * I've included this in Level 1 purely as an anchor point for default
+ * attributes. In Level 2 it should enable the ChildRule support.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class ElementDefinitionImpl
+ extends ParentNode {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -8373890672670022714L;
+
+ //
+ // Data
+ //
+
+ /** Element definition name. */
+ protected String name;
+
+ /** Default attributes. */
+ protected NamedNodeMapImpl attributes;
+
+ //
+ // Constructors
+ //
+
+ /** Factory constructor. */
+ public ElementDefinitionImpl(CoreDocumentImpl ownerDocument, String name) {
+ super(ownerDocument);
+ this.name = name;
+ attributes = new NamedNodeMapImpl(ownerDocument);
+ }
+
+ //
+ // Node methods
+ //
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public short getNodeType() {
+ return NodeImpl.ELEMENT_DEFINITION_NODE;
+ }
+
+ /**
+ * Returns the element definition name
+ */
+ public String getNodeName() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return name;
+ }
+
+ /**
+ * Replicate this object.
+ */
+ public Node cloneNode(boolean deep) {
+
+ ElementDefinitionImpl newnode =
+ (ElementDefinitionImpl) super.cloneNode(deep);
+ // NamedNodeMap must be explicitly replicated to avoid sharing
+ newnode.attributes = attributes.cloneMap(newnode);
+ return newnode;
+
+ } // cloneNode(boolean):Node
+
+ /**
+ * Query the attributes defined on this Element.
+ *
+ * In the base implementation this Map simply contains Attribute objects
+ * representing the defaults. In a more serious implementation, it would
+ * contain AttributeDefinitionImpl objects for all declared Attributes,
+ * indicating which are Default, DefaultFixed, Implicit and/or Required.
+ *
+ * @return org.w3c.dom.NamedNodeMap containing org.w3c.dom.Attribute
+ */
+ public NamedNodeMap getAttributes() {
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return attributes;
+
+ } // getAttributes():NamedNodeMap
+
+} // class ElementDefinitionImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/ElementImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/ElementImpl.java
new file mode 100644
index 0000000..59db6de
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/ElementImpl.java
@@ -0,0 +1,1375 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.apache.xerces.util.URI;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.ElementTraversal;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.w3c.dom.TypeInfo;
+
+/**
+ * Elements represent most of the "markup" and structure of the
+ * document. They contain both the data for the element itself
+ * (element name and attributes), and any contained nodes, including
+ * document text (as children).
+ *
+ * Elements may have Attributes associated with them; the API for this is
+ * defined in Node, but the function is implemented here. In general, XML
+ * applications should retrive Attributes as Nodes, since they may contain
+ * entity references and hence be a fairly complex sub-tree. HTML users will
+ * be dealing with simple string values, and convenience methods are provided
+ * to work in terms of Strings.
+ *
+ * ElementImpl does not support Namespaces. ElementNSImpl, which inherits from
+ * it, does.
+ *
+ * @xerces.internal
+ *
+ * @see ElementNSImpl
+ *
+ * @author Arnaud Le Hors, IBM
+ * @author Joe Kesselman, IBM
+ * @author Andy Clark, IBM
+ * @author Ralf Pfeiffer, IBM
+ * @author Michael Glavassevich, IBM
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class ElementImpl
+ extends ParentNode
+ implements Element, ElementTraversal, TypeInfo {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 3717253516652722278L;
+ //
+ // Data
+ //
+
+ /** Element name. */
+ protected String name;
+
+ /** Attributes. */
+ protected AttributeMap attributes;
+
+ //
+ // Constructors
+ //
+
+ /** Factory constructor. */
+ public ElementImpl(CoreDocumentImpl ownerDoc, String name) {
+ super(ownerDoc);
+ this.name = name;
+ needsSyncData(true); // synchronizeData will initialize attributes
+ }
+
+ // for ElementNSImpl
+ protected ElementImpl() {}
+
+ // Support for DOM Level 3 renameNode method.
+ // Note: This only deals with part of the pb. CoreDocumentImpl
+ // does all the work.
+ void rename(String name) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (ownerDocument.errorChecking) {
+ int colon1 = name.indexOf(':');
+ if(colon1 != -1){
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NAMESPACE_ERR",
+ null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ if (!CoreDocumentImpl.isXMLName(name, ownerDocument.isXML11Version())) {
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "INVALID_CHARACTER_ERR", null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR,
+ msg);
+ }
+ }
+ this.name = name;
+ reconcileDefaultAttributes();
+ }
+
+ //
+ // Node methods
+ //
+
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public short getNodeType() {
+ return Node.ELEMENT_NODE;
+ }
+
+ /**
+ * Returns the element name
+ */
+ public String getNodeName() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return name;
+ }
+
+ /**
+ * Retrieve all the Attributes as a set. Note that this API is inherited
+ * from Node rather than specified on Element; in fact only Elements will
+ * ever have Attributes, but they want to allow folks to "blindly" operate
+ * on the tree as a set of Nodes.
+ */
+ public NamedNodeMap getAttributes() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (attributes == null) {
+ attributes = new AttributeMap(this, null);
+ }
+ return attributes;
+
+ } // getAttributes():NamedNodeMap
+
+ /**
+ * Return a duplicate copy of this Element. Note that its children
+ * will not be copied unless the "deep" flag is true, but Attributes
+ * are always replicated.
+ *
+ * @see org.w3c.dom.Node#cloneNode(boolean)
+ */
+ public Node cloneNode(boolean deep) {
+
+ ElementImpl newnode = (ElementImpl) super.cloneNode(deep);
+ // Replicate NamedNodeMap rather than sharing it.
+ if (attributes != null) {
+ newnode.attributes = (AttributeMap) attributes.cloneMap(newnode);
+ }
+ return newnode;
+
+ } // cloneNode(boolean):Node
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * Retrieve baseURI
+ */
+ public String getBaseURI() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ // Absolute base URI is computed according to
+ // XML Base (http://www.w3.org/TR/xmlbase/#granularity)
+ // 1. The base URI specified by an xml:base attribute on the element,
+ // if one exists
+ if (attributes != null) {
+ final Attr attrNode = getXMLBaseAttribute();
+ if (attrNode != null) {
+ final String uri = attrNode.getNodeValue();
+ if (uri.length() != 0) {// attribute value is always empty string
+ try {
+ URI _uri = new URI(uri, true);
+ // If the URI is already absolute return it; otherwise it's relative and we need to resolve it.
+ if (_uri.isAbsoluteURI()) {
+ return _uri.toString();
+ }
+
+ // Make any parentURI into a URI object to use with the URI(URI, String) constructor
+ String parentBaseURI = (this.ownerNode != null) ? this.ownerNode.getBaseURI() : null;
+ if (parentBaseURI != null) {
+ try {
+ URI _parentBaseURI = new URI(parentBaseURI);
+ _uri.absolutize(_parentBaseURI);
+ return _uri.toString();
+ }
+ catch (org.apache.xerces.util.URI.MalformedURIException ex) {
+ // This should never happen: parent should have checked the URI and returned null if invalid.
+ return null;
+ }
+ }
+ // REVISIT: what should happen in this case?
+ return null;
+ }
+ catch (org.apache.xerces.util.URI.MalformedURIException ex) {
+ return null;
+ }
+ }
+ }
+ }
+
+ // 2.the base URI of the element's parent element within the
+ // document or external entity, if one exists
+ // 3. the base URI of the document entity or external entity
+ // containing the element
+
+ // ownerNode serves as a parent or as document
+ return (this.ownerNode != null) ? this.ownerNode.getBaseURI() : null;
+ } //getBaseURI
+
+ /**
+ * NON-DOM
+ * Returns the xml:base attribute.
+ */
+ protected Attr getXMLBaseAttribute() {
+ return (Attr) attributes.getNamedItem("xml:base");
+ } // getXMLBaseAttribute():Attr
+
+ /**
+ * NON-DOM
+ * set the ownerDocument of this node, its children, and its attributes
+ */
+ protected void setOwnerDocument(CoreDocumentImpl doc) {
+ super.setOwnerDocument(doc);
+ if (attributes != null) {
+ attributes.setOwnerDocument(doc);
+ }
+ }
+
+ //
+ // Element methods
+ //
+
+ /**
+ * Look up a single Attribute by name. Returns the Attribute's
+ * string value, or an empty string (NOT null!) to indicate that the
+ * name did not map to a currently defined attribute.
+ *
+ * Note: Attributes may contain complex node trees. This method
+ * returns the "flattened" string obtained from Attribute.getValue().
+ * If you need the structure information, see getAttributeNode().
+ */
+ public String getAttribute(String name) {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (attributes == null) {
+ return "";
+ }
+ Attr attr = (Attr)(attributes.getNamedItem(name));
+ return (attr == null) ? "" : attr.getValue();
+
+ } // getAttribute(String):String
+
+
+ /**
+ * Look up a single Attribute by name. Returns the Attribute Node,
+ * so its complete child tree is available. This could be important in
+ * XML, where the string rendering may not be sufficient information.
+ *
+ * If no matching attribute is available, returns null.
+ */
+ public Attr getAttributeNode(String name) {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (attributes == null) {
+ return null;
+ }
+ return (Attr)attributes.getNamedItem(name);
+
+ } // getAttributeNode(String):Attr
+
+
+ /**
+ * Returns a NodeList of all descendent nodes (children,
+ * grandchildren, and so on) which are Elements and which have the
+ * specified tag name.
+ *
+ * Note: NodeList is a "live" view of the DOM. Its contents will
+ * change as the DOM changes, and alterations made to the NodeList
+ * will be reflected in the DOM.
+ *
+ * @param tagname The type of element to gather. To obtain a list of
+ * all elements no matter what their names, use the wild-card tag
+ * name "*".
+ *
+ * @see DeepNodeListImpl
+ */
+ public NodeList getElementsByTagName(String tagname) {
+ return new DeepNodeListImpl(this,tagname);
+ }
+
+ /**
+ * Returns the name of the Element. Note that Element.nodeName() is
+ * defined to also return the tag name.
+ *
+ * This is case-preserving in XML. HTML should uppercasify it on the
+ * way in.
+ */
+ public String getTagName() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return name;
+ }
+
+ /**
+ * In "normal form" (as read from a source file), there will never be two
+ * Text children in succession. But DOM users may create successive Text
+ * nodes in the course of manipulating the document. Normalize walks the
+ * sub-tree and merges adjacent Texts, as if the DOM had been written out
+ * and read back in again. This simplifies implementation of higher-level
+ * functions that may want to assume that the document is in standard form.
+ *
+ * To normalize a Document, normalize its top-level Element child.
+ *
+ * As of PR-DOM-Level-1-19980818, CDATA -- despite being a subclass of
+ * Text -- is considered "markup" and will _not_ be merged either with
+ * normal Text or with other CDATASections.
+ */
+ public void normalize() {
+ // No need to normalize if already normalized.
+ if (isNormalized()) {
+ return;
+ }
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ ChildNode kid, next;
+ for (kid = firstChild; kid != null; kid = next) {
+ next = kid.nextSibling;
+
+ // If kid is a text node, we need to check for one of two
+ // conditions:
+ // 1) There is an adjacent text node
+ // 2) There is no adjacent text node, but kid is
+ // an empty text node.
+ if ( kid.getNodeType() == Node.TEXT_NODE )
+ {
+ // If an adjacent text node, merge it with kid
+ if ( next!=null && next.getNodeType() == Node.TEXT_NODE )
+ {
+ ((Text)kid).appendData(next.getNodeValue());
+ removeChild( next );
+ next = kid; // Don't advance; there might be another.
+ }
+ else
+ {
+ // If kid is empty, remove it
+ if ( kid.getNodeValue() == null || kid.getNodeValue().length() == 0 ) {
+ removeChild( kid );
+ }
+ }
+ }
+
+ // Otherwise it might be an Element, which is handled recursively
+ else if (kid.getNodeType() == Node.ELEMENT_NODE) {
+ kid.normalize();
+ }
+ }
+
+ // We must also normalize all of the attributes
+ if ( attributes!=null )
+ {
+ for( int i=0; i
+ * The default logic is actually implemented in NamedNodeMapImpl.
+ * PR-DOM-Level-1-19980818 doesn't fully address the DTD, so some
+ * of this behavior is likely to change in future versions. ?????
+ *
+ * Note that this call "succeeds" even if no attribute by this name
+ * existed -- unlike removeAttributeNode, which will throw a not-found
+ * exception in that case.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if the node is
+ * readonly.
+ */
+ public void removeAttribute(String name) {
+
+ if (ownerDocument.errorChecking && isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ if (attributes == null) {
+ return;
+ }
+
+ attributes.safeRemoveNamedItem(name);
+
+ } // removeAttribute(String)
+
+
+ /**
+ * Remove the specified attribute/value pair. If the removed
+ * Attribute has a default value, it is immediately replaced.
+ *
+ * NOTE: Specifically removes THIS NODE -- not the node with this
+ * name, nor the node with these contents. If the specific Attribute
+ * object passed in is not stored in this Element, we throw a
+ * DOMException. If you really want to remove an attribute by name,
+ * use removeAttribute().
+ *
+ * @return the Attribute object that was removed.
+ * @throws DOMException(NOT_FOUND_ERR) if oldattr is not an attribute of
+ * this Element.
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if the node is
+ * readonly.
+ */
+ public Attr removeAttributeNode(Attr oldAttr)
+ throws DOMException {
+
+ if (ownerDocument.errorChecking && isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ if (attributes == null) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+ return (Attr) attributes.removeItem(oldAttr, true);
+
+ } // removeAttributeNode(Attr):Attr
+
+
+ /**
+ * Add a new name/value pair, or replace the value of the existing
+ * attribute having that name.
+ *
+ * Note: this method supports only the simplest kind of Attribute,
+ * one whose value is a string contained in a single Text node.
+ * If you want to assert a more complex value (which XML permits,
+ * though HTML doesn't), see setAttributeNode().
+ *
+ * The attribute is created with specified=true, meaning it's an
+ * explicit value rather than inherited from the DTD as a default.
+ * Again, setAttributeNode can be used to achieve other results.
+ *
+ * @throws DOMException(INVALID_NAME_ERR) if the name is not acceptable.
+ * (Attribute factory will do that test for us.)
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if the node is
+ * readonly.
+ */
+ public void setAttribute(String name, String value) {
+
+ if (ownerDocument.errorChecking && isReadOnly()) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NO_MODIFICATION_ALLOWED_ERR",
+ null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ Attr newAttr = getAttributeNode(name);
+ if (newAttr == null) {
+ newAttr = getOwnerDocument().createAttribute(name);
+
+ if (attributes == null) {
+ attributes = new AttributeMap(this, null);
+ }
+
+ newAttr.setNodeValue(value);
+ attributes.setNamedItem(newAttr);
+ }
+ else {
+ newAttr.setNodeValue(value);
+ }
+
+ } // setAttribute(String,String)
+
+ /**
+ * Add a new attribute/value pair, or replace the value of the
+ * existing attribute with that name.
+ *
+ * This method allows you to add an Attribute that has already been
+ * constructed, and hence avoids the limitations of the simple
+ * setAttribute() call. It can handle attribute values that have
+ * arbitrarily complex tree structure -- in particular, those which
+ * had entity references mixed into their text.
+ *
+ * @throws DOMException(INUSE_ATTRIBUTE_ERR) if the Attribute object
+ * has already been assigned to another Element.
+ */
+ public Attr setAttributeNode(Attr newAttr)
+ throws DOMException
+ {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ if (ownerDocument.errorChecking) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
+ }
+
+ if (newAttr.getOwnerDocument() != ownerDocument) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+ }
+ }
+
+ if (attributes == null) {
+ attributes = new AttributeMap(this, null);
+ }
+ // This will throw INUSE if necessary
+ return (Attr) attributes.setNamedItem(newAttr);
+
+ } // setAttributeNode(Attr):Attr
+
+ //
+ // DOM2: Namespace methods
+ //
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Retrieves an attribute value by local name and namespace URI.
+ *
+ * @param namespaceURI
+ * The namespace URI of the attribute to
+ * retrieve.
+ * @param localName The local name of the attribute to retrieve.
+ * @return String The Attr value as a string, or empty string
+ * if that attribute
+ * does not have a specified or default value.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public String getAttributeNS(String namespaceURI, String localName) {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ if (attributes == null) {
+ return "";
+ }
+
+ Attr attr = (Attr)(attributes.getNamedItemNS(namespaceURI, localName));
+ return (attr == null) ? "" : attr.getValue();
+
+ } // getAttributeNS(String,String):String
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Adds a new attribute.
+ * If the given namespaceURI is null or an empty string and the
+ * qualifiedName has a prefix that is "xml", the new attribute is bound to
+ * the predefined namespace "http://www.w3.org/XML/1998/namespace"
+ * [Namespaces]. If an attribute with the same local name and namespace
+ * URI is already present on the element, its prefix is changed to be the
+ * prefix part of the qualifiedName, and its value is changed to be the
+ * value parameter. This value is a simple string, it is not parsed as it
+ * is being set. So any markup (such as syntax to be recognized as an
+ * entity reference) is treated as literal text, and needs to be
+ * appropriately escaped by the implementation when it is written out. In
+ * order to assign an attribute value that contains entity references, the
+ * user must create an Attr node plus any Text and EntityReference nodes,
+ * build the appropriate subtree, and use setAttributeNodeNS or
+ * setAttributeNode to assign it as the value of an attribute.
+ *
+ * @param namespaceURI The namespace URI of the attribute to create
+ * or alter.
+ * @param qualifiedName The qualified name of the attribute to create or
+ * alter.
+ * @param value The value to set in string form.
+ * @throws INVALID_CHARACTER_ERR: Raised if the specified
+ * name contains an invalid character.
+ *
+ * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if this
+ * node is readonly.
+ *
+ * @throws NAMESPACE_ERR: Raised if the qualifiedName
+ * has a prefix that is "xml" and the namespaceURI
+ * is neither null nor an empty string nor
+ * "http://www.w3.org/XML/1998/namespace", or if
+ * the qualifiedName has a prefix that is "xmlns"
+ * but the namespaceURI is neither null nor an
+ * empty string, or if if the qualifiedName has a
+ * prefix different from "xml" and "xmlns" and the
+ * namespaceURI is null or an empty string.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public void setAttributeNS(String namespaceURI,String qualifiedName,
+ String value) {
+ if (ownerDocument.errorChecking && isReadOnly()) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NO_MODIFICATION_ALLOWED_ERR",
+ null);
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
+ }
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ int index = qualifiedName.indexOf(':');
+ String prefix, localName;
+ if (index < 0) {
+ prefix = null;
+ localName = qualifiedName;
+ }
+ else {
+ prefix = qualifiedName.substring(0, index);
+ localName = qualifiedName.substring(index + 1);
+ }
+ Attr newAttr = getAttributeNodeNS(namespaceURI, localName);
+ if (newAttr == null) {
+ // REVISIT: this is not efficient, we are creating twice the same
+ // strings for prefix and localName.
+ newAttr = getOwnerDocument().createAttributeNS(
+ namespaceURI,
+ qualifiedName);
+ if (attributes == null) {
+ attributes = new AttributeMap(this, null);
+ }
+ newAttr.setNodeValue(value);
+ attributes.setNamedItemNS(newAttr);
+ }
+ else {
+ if (newAttr instanceof AttrNSImpl){
+ // change prefix and value
+ ((AttrNSImpl)newAttr).name= (prefix!=null)?(prefix+":"+localName):localName;
+ }
+ else {
+ // This case may happen if user calls:
+ // elem.setAttribute("name", "value");
+ // elem.setAttributeNS(null, "name", "value");
+ // This case is not defined by the DOM spec, we choose
+ // to create a new attribute in this case and remove an old one from the tree
+ // note this might cause events to be propagated or user data to be lost
+ newAttr = ((CoreDocumentImpl)getOwnerDocument()).createAttributeNS(namespaceURI, qualifiedName, localName);
+ attributes.setNamedItemNS(newAttr);
+ }
+
+ newAttr.setNodeValue(value);
+ }
+
+ } // setAttributeNS(String,String,String)
+
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Removes an attribute by local name and namespace URI. If the removed
+ * attribute has a default value it is immediately replaced.
+ * The replacing attribute has the same namespace URI and local name,
+ * as well as the original prefix.
+ *
+ * @param namespaceURI The namespace URI of the attribute to remove.
+ *
+ * @param localName The local name of the attribute to remove.
+ * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if this
+ * node is readonly.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public void removeAttributeNS(String namespaceURI, String localName) {
+
+ if (ownerDocument.errorChecking && isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ if (attributes == null) {
+ return;
+ }
+
+ attributes.safeRemoveNamedItemNS(namespaceURI, localName);
+
+ } // removeAttributeNS(String,String)
+
+ /**
+ * Retrieves an Attr node by local name and namespace URI.
+ *
+ * @param namespaceURI The namespace URI of the attribute to
+ * retrieve.
+ * @param localName The local name of the attribute to retrieve.
+ * @return Attr The Attr node with the specified attribute
+ * local name and namespace
+ * URI or null if there is no such attribute.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public Attr getAttributeNodeNS(String namespaceURI, String localName){
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (attributes == null) {
+ return null;
+ }
+ return (Attr)attributes.getNamedItemNS(namespaceURI, localName);
+
+ } // getAttributeNodeNS(String,String):Attr
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Adds a new attribute. If an attribute with that local name and
+ * namespace URI is already present in the element, it is replaced
+ * by the new one.
+ *
+ * @param newAttr The Attr node to add to the attribute list. When
+ * the Node has no namespaceURI, this method behaves
+ * like setAttributeNode.
+ * @return Attr If the newAttr attribute replaces an existing attribute
+ * with the same local name and namespace URI, the *
+ * previously existing Attr node is returned, otherwise
+ * null is returned.
+ * @throws WRONG_DOCUMENT_ERR: Raised if newAttr
+ * was created from a different document than the one that
+ * created the element.
+ *
+ * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if
+ * this node is readonly.
+ *
+ * @throws INUSE_ATTRIBUTE_ERR: Raised if newAttr is
+ * already an attribute of another Element object. The
+ * DOM user must explicitly clone Attr nodes to re-use
+ * them in other elements.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public Attr setAttributeNodeNS(Attr newAttr)
+ throws DOMException
+ {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (ownerDocument.errorChecking) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
+ }
+ if (newAttr.getOwnerDocument() != ownerDocument) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+ }
+ }
+
+ if (attributes == null) {
+ attributes = new AttributeMap(this, null);
+ }
+ // This will throw INUSE if necessary
+ return (Attr) attributes.setNamedItemNS(newAttr);
+
+ } // setAttributeNodeNS(Attr):Attr
+
+ /**
+ * NON-DOM: sets attribute node for this element
+ */
+ protected int setXercesAttributeNode (Attr attr){
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ if (attributes == null) {
+ attributes = new AttributeMap(this, null);
+ }
+ return attributes.addItem(attr);
+
+ }
+
+ /**
+ * NON-DOM: get inded of an attribute
+ */
+ protected int getXercesAttribute(String namespaceURI, String localName){
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (attributes == null) {
+ return -1;
+ }
+ return attributes.getNamedItemIndex(namespaceURI, localName);
+
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ */
+ public boolean hasAttributes() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return (attributes != null && attributes.getLength() != 0);
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ */
+ public boolean hasAttribute(String name) {
+ return getAttributeNode(name) != null;
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ */
+ public boolean hasAttributeNS(String namespaceURI, String localName) {
+ return getAttributeNodeNS(namespaceURI, localName) != null;
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Returns a NodeList of all the Elements with a given local name and
+ * namespace URI in the order in which they would be encountered in a
+ * preorder traversal of the Document tree, starting from this node.
+ *
+ * @param namespaceURI The namespace URI of the elements to match
+ * on. The special value "*" matches all
+ * namespaces. When it is null or an empty
+ * string, this method behaves like
+ * getElementsByTagName.
+ * @param localName The local name of the elements to match on.
+ * The special value "*" matches all local names.
+ * @return NodeList A new NodeList object containing all the matched
+ * Elements.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public NodeList getElementsByTagNameNS(String namespaceURI,
+ String localName) {
+ return new DeepNodeListImpl(this, namespaceURI, localName);
+ }
+
+ /**
+ * DOM Level 3 WD- Experimental.
+ * Override inherited behavior from NodeImpl and ParentNode to check on
+ * attributes
+ */
+ public boolean isEqualNode(Node arg) {
+ if (!super.isEqualNode(arg)) {
+ return false;
+ }
+ boolean hasAttrs = hasAttributes();
+ if (hasAttrs != ((Element) arg).hasAttributes()) {
+ return false;
+ }
+ if (hasAttrs) {
+ NamedNodeMap map1 = getAttributes();
+ NamedNodeMap map2 = ((Element) arg).getAttributes();
+ int len = map1.getLength();
+ if (len != map2.getLength()) {
+ return false;
+ }
+ for (int i = 0; i < len; i++) {
+ Node n1 = map1.item(i);
+ if (n1.getLocalName() == null) { // DOM Level 1 Node
+ Node n2 = map2.getNamedItem(n1.getNodeName());
+ if (n2 == null || !((NodeImpl) n1).isEqualNode(n2)) {
+ return false;
+ }
+ }
+ else {
+ Node n2 = map2.getNamedItemNS(n1.getNamespaceURI(),
+ n1.getLocalName());
+ if (n2 == null || !((NodeImpl) n1).isEqualNode(n2)) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * DOM Level 3: register the given attribute node as an ID attribute
+ */
+ public void setIdAttributeNode(Attr at, boolean makeId) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (ownerDocument.errorChecking) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
+ }
+
+ if (at.getOwnerElement() != this) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+ }
+ ((AttrImpl) at).isIdAttribute(makeId);
+ if (!makeId) {
+ ownerDocument.removeIdentifier(at.getValue());
+ }
+ else {
+ ownerDocument.putIdentifier(at.getValue(), this);
+ }
+ }
+
+ /**
+ * DOM Level 3: register the given attribute node as an ID attribute
+ */
+ public void setIdAttribute(String name, boolean makeId) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ Attr at = getAttributeNode(name);
+
+ if( at == null){
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+
+ if (ownerDocument.errorChecking) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
+ }
+
+ if (at.getOwnerElement() != this) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+ }
+
+ ((AttrImpl) at).isIdAttribute(makeId);
+ if (!makeId) {
+ ownerDocument.removeIdentifier(at.getValue());
+ }
+ else {
+ ownerDocument.putIdentifier(at.getValue(), this);
+ }
+ }
+
+ /**
+ * DOM Level 3: register the given attribute node as an ID attribute
+ */
+ public void setIdAttributeNS(String namespaceURI, String localName,
+ boolean makeId) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ Attr at = getAttributeNodeNS(namespaceURI, localName);
+
+ if( at == null){
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+
+ if (ownerDocument.errorChecking) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
+ }
+
+ if (at.getOwnerElement() != this) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+ }
+ ((AttrImpl) at).isIdAttribute(makeId);
+ if (!makeId) {
+ ownerDocument.removeIdentifier(at.getValue());
+ }
+ else {
+ ownerDocument.putIdentifier(at.getValue(), this);
+ }
+ }
+
+ /**
+ * @see org.w3c.dom.TypeInfo#getTypeName()
+ */
+ public String getTypeName() {
+ return null;
+ }
+
+ /**
+ * @see org.w3c.dom.TypeInfo#getTypeNamespace()
+ */
+ public String getTypeNamespace() {
+ return null;
+ }
+
+ /**
+ * Introduced in DOM Level 3.
+ * Checks if a type is derived from another by restriction. See:
+ * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
+ *
+ * @param typeNamespaceArg
+ * The namspace of the ancestor type declaration
+ * @param typeNameArg
+ * The name of the ancestor type declaration
+ * @param derivationMethod
+ * The derivation method
+ *
+ * @return boolean True if the type is derived by restriciton for the
+ * reference type
+ */
+ public boolean isDerivedFrom(String typeNamespaceArg,
+ String typeNameArg,
+ int derivationMethod) {
+
+ return false;
+ }
+
+ /**
+ * Method getSchemaTypeInfo.
+ * @return TypeInfo
+ */
+ public TypeInfo getSchemaTypeInfo(){
+ if(needsSyncData()) {
+ synchronizeData();
+ }
+ return this;
+ }
+
+ //
+ // Public methods
+ //
+
+ /**
+ * NON-DOM: Subclassed to flip the attributes' readonly switch as well.
+ * @see NodeImpl#setReadOnly
+ */
+ public void setReadOnly(boolean readOnly, boolean deep) {
+ super.setReadOnly(readOnly,deep);
+ if (attributes != null) {
+ attributes.setReadOnly(readOnly,true);
+ }
+ }
+
+
+
+ //
+ // Protected methods
+ //
+
+ /** Synchronizes the data (name and value) for fast nodes. */
+ protected void synchronizeData() {
+
+ // no need to sync in the future
+ needsSyncData(false);
+
+ // we don't want to generate any event for this so turn them off
+ boolean orig = ownerDocument.getMutationEvents();
+ ownerDocument.setMutationEvents(false);
+
+ // attributes
+ setupDefaultAttributes();
+
+ // set mutation events flag back to its original value
+ ownerDocument.setMutationEvents(orig);
+
+ } // synchronizeData()
+
+ // support for DOM Level 3 renameNode method
+ // @param el The element from which to take the attributes
+ void moveSpecifiedAttributes(ElementImpl el) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (el.hasAttributes()) {
+ if (attributes == null) {
+ attributes = new AttributeMap(this, null);
+ }
+ attributes.moveSpecifiedAttributes(el.attributes);
+ }
+ }
+
+ /** Setup the default attributes. */
+ protected void setupDefaultAttributes() {
+ NamedNodeMapImpl defaults = getDefaultAttributes();
+ if (defaults != null) {
+ attributes = new AttributeMap(this, defaults);
+ }
+ }
+
+ /** Reconcile default attributes. */
+ protected void reconcileDefaultAttributes() {
+ if (attributes != null) {
+ NamedNodeMapImpl defaults = getDefaultAttributes();
+ attributes.reconcileDefaults(defaults);
+ }
+ }
+
+ /** Get the default attributes. */
+ protected NamedNodeMapImpl getDefaultAttributes() {
+
+ DocumentTypeImpl doctype =
+ (DocumentTypeImpl) ownerDocument.getDoctype();
+ if (doctype == null) {
+ return null;
+ }
+ ElementDefinitionImpl eldef =
+ (ElementDefinitionImpl)doctype.getElements()
+ .getNamedItem(getNodeName());
+ if (eldef == null) {
+ return null;
+ }
+ return (NamedNodeMapImpl) eldef.getAttributes();
+
+ } // getDefaultAttributes()
+
+ //
+ // ElementTraversal methods
+ //
+
+ /**
+ * @see
+ * Element Traversal Specification
+ */
+ public final int getChildElementCount() {
+ int count = 0;
+ Element child = getFirstElementChild();
+ while (child != null) {
+ ++count;
+ child = ((ElementImpl) child).getNextElementSibling();
+ }
+ return count;
+ } // getChildElementCount():int
+
+ /**
+ * @see
+ * Element Traversal Specification
+ */
+ public final Element getFirstElementChild() {
+ Node n = getFirstChild();
+ while (n != null) {
+ switch (n.getNodeType()) {
+ case Node.ELEMENT_NODE:
+ return (Element) n;
+ case Node.ENTITY_REFERENCE_NODE:
+ final Element e = getFirstElementChild(n);
+ if (e != null) {
+ return e;
+ }
+ break;
+ }
+ n = n.getNextSibling();
+ }
+ return null;
+ } // getFirstElementChild():Element
+
+ /**
+ * @see
+ * Element Traversal Specification
+ */
+ public final Element getLastElementChild() {
+ Node n = getLastChild();
+ while (n != null) {
+ switch (n.getNodeType()) {
+ case Node.ELEMENT_NODE:
+ return (Element) n;
+ case Node.ENTITY_REFERENCE_NODE:
+ final Element e = getLastElementChild(n);
+ if (e != null) {
+ return e;
+ }
+ break;
+ }
+ n = n.getPreviousSibling();
+ }
+ return null;
+ } // getLastElementChild():Element
+
+ /**
+ * @see
+ * Element Traversal Specification
+ */
+ public final Element getNextElementSibling() {
+ Node n = getNextLogicalSibling(this);
+ while (n != null) {
+ switch (n.getNodeType()) {
+ case Node.ELEMENT_NODE:
+ return (Element) n;
+ case Node.ENTITY_REFERENCE_NODE:
+ final Element e = getFirstElementChild(n);
+ if (e != null) {
+ return e;
+ }
+ break;
+ }
+ n = getNextLogicalSibling(n);
+ }
+ return null;
+ } // getNextElementSibling():Element
+
+ /**
+ * @see
+ * Element Traversal Specification
+ */
+ public final Element getPreviousElementSibling() {
+ Node n = getPreviousLogicalSibling(this);
+ while (n != null) {
+ switch (n.getNodeType()) {
+ case Node.ELEMENT_NODE:
+ return (Element) n;
+ case Node.ENTITY_REFERENCE_NODE:
+ final Element e = getLastElementChild(n);
+ if (e != null) {
+ return e;
+ }
+ break;
+ }
+ n = getPreviousLogicalSibling(n);
+ }
+ return null;
+ } // getPreviousElementSibling():Element
+
+ // Returns the first element node found from a
+ // non-recursive in order traversal of the given node.
+ private Element getFirstElementChild(Node n) {
+ final Node top = n;
+ while (n != null) {
+ if (n.getNodeType() == Node.ELEMENT_NODE) {
+ return (Element) n;
+ }
+ Node next = n.getFirstChild();
+ while (next == null) {
+ if (top == n) {
+ break;
+ }
+ next = n.getNextSibling();
+ if (next == null) {
+ n = n.getParentNode();
+ if (n == null || top == n) {
+ return null;
+ }
+ }
+ }
+ n = next;
+ }
+ return null;
+ } // getFirstElementChild(Node):Element
+
+ // Returns the first element node found from a
+ // non-recursive reverse order traversal of the given node.
+ private Element getLastElementChild(Node n) {
+ final Node top = n;
+ while (n != null) {
+ if (n.getNodeType() == Node.ELEMENT_NODE) {
+ return (Element) n;
+ }
+ Node next = n.getLastChild();
+ while (next == null) {
+ if (top == n) {
+ break;
+ }
+ next = n.getPreviousSibling();
+ if (next == null) {
+ n = n.getParentNode();
+ if (n == null || top == n) {
+ return null;
+ }
+ }
+ }
+ n = next;
+ }
+ return null;
+ } // getLastElementChild(Node):Element
+
+ // Returns the next logical sibling with respect to the given node.
+ private Node getNextLogicalSibling(Node n) {
+ Node next = n.getNextSibling();
+ // If "n" has no following sibling and its parent is an entity reference node we
+ // need to continue the search through the following siblings of the entity
+ // reference as these are logically siblings of the given node.
+ if (next == null) {
+ Node parent = n.getParentNode();
+ while (parent != null && parent.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+ next = parent.getNextSibling();
+ if (next != null) {
+ break;
+ }
+ parent = parent.getParentNode();
+ }
+ }
+ return next;
+ } // getNextLogicalSibling(Node):Node
+
+ // Returns the previous logical sibling with respect to the given node.
+ private Node getPreviousLogicalSibling(Node n) {
+ Node prev = n.getPreviousSibling();
+ // If "n" has no previous sibling and its parent is an entity reference node we
+ // need to continue the search through the previous siblings of the entity
+ // reference as these are logically siblings of the given node.
+ if (prev == null) {
+ Node parent = n.getParentNode();
+ while (parent != null && parent.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+ prev = parent.getPreviousSibling();
+ if (prev != null) {
+ break;
+ }
+ parent = parent.getParentNode();
+ }
+ }
+ return prev;
+ } // getPreviousLogicalSibling(Node):Node
+
+} // class ElementImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/ElementNSImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/ElementNSImpl.java
new file mode 100644
index 0000000..6d00e4d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/ElementNSImpl.java
@@ -0,0 +1,378 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl;
+import org.apache.xerces.impl.xs.XSComplexTypeDecl;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xs.XSTypeDefinition;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+
+
+
+/**
+ * ElementNSImpl inherits from ElementImpl and adds namespace support.
+ *
+ * The qualified name is the node name, and we store localName which is also
+ * used in all queries. On the other hand we recompute the prefix when
+ * necessary.
+ *
+ * @xerces.internal
+ *
+ * @author Elena litani, IBM
+ * @author Neeraj Bajaj, Sun Microsystems
+ * @version $Id$
+ */
+public class ElementNSImpl
+ extends ElementImpl {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -9142310625494392642L;
+ static final String xmlURI = "http://www.w3.org/XML/1998/namespace";
+
+ //
+ // Data
+ //
+
+ /** DOM2: Namespace URI. */
+ protected String namespaceURI;
+
+ /** DOM2: localName. */
+ protected String localName;
+
+ /** DOM3: type information */
+ // REVISIT: we are losing the type information in DOM during serialization
+ transient XSTypeDefinition type;
+
+ protected ElementNSImpl() {
+ super();
+ }
+ /**
+ * DOM2: Constructor for Namespace implementation.
+ */
+ protected ElementNSImpl(CoreDocumentImpl ownerDocument,
+ String namespaceURI,
+ String qualifiedName)
+ throws DOMException
+ {
+ super(ownerDocument, qualifiedName);
+ setName(namespaceURI, qualifiedName);
+ }
+
+ private void setName(String namespaceURI, String qname) {
+
+ String prefix;
+ // DOM Level 3: namespace URI is never empty string.
+ this.namespaceURI = namespaceURI;
+ if (namespaceURI != null) {
+ //convert the empty string to 'null'
+ this.namespaceURI = (namespaceURI.length() == 0) ? null : namespaceURI;
+ }
+
+ int colon1, colon2 ;
+
+ //NAMESPACE_ERR:
+ //1. if the qualified name is 'null' it is malformed.
+ //2. or if the qualifiedName is null and the namespaceURI is different from null,
+ // We dont need to check for namespaceURI != null, if qualified name is null throw DOMException.
+ if(qname == null){
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NAMESPACE_ERR",
+ null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ else{
+ colon1 = qname.indexOf(':');
+ colon2 = qname.lastIndexOf(':');
+ }
+
+ ownerDocument.checkNamespaceWF(qname, colon1, colon2);
+ if (colon1 < 0) {
+ // there is no prefix
+ localName = qname;
+ if (ownerDocument.errorChecking) {
+ ownerDocument.checkQName(null, localName);
+ if (qname.equals("xmlns")
+ && (namespaceURI == null
+ || !namespaceURI.equals(NamespaceContext.XMLNS_URI))
+ || (namespaceURI!=null && namespaceURI.equals(NamespaceContext.XMLNS_URI)
+ && !qname.equals("xmlns"))) {
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NAMESPACE_ERR",
+ null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ }
+ }//there is a prefix
+ else {
+ prefix = qname.substring(0, colon1);
+ localName = qname.substring(colon2 + 1);
+
+ //NAMESPACE_ERR:
+ //1. if the qualifiedName has a prefix and the namespaceURI is null,
+
+ //2. or if the qualifiedName has a prefix that is "xml" and the namespaceURI
+ //is different from " http://www.w3.org/XML/1998/namespace"
+
+ if (ownerDocument.errorChecking) {
+ if( namespaceURI == null || ( prefix.equals("xml") && !namespaceURI.equals(NamespaceContext.XML_URI) )){
+ String msg =
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NAMESPACE_ERR",
+ null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+
+ ownerDocument.checkQName(prefix, localName);
+ ownerDocument.checkDOMNSErr(prefix, namespaceURI);
+ }
+ }
+ }
+
+ // when local name is known
+ protected ElementNSImpl(CoreDocumentImpl ownerDocument,
+ String namespaceURI, String qualifiedName,
+ String localName)
+ throws DOMException
+ {
+ super(ownerDocument, qualifiedName);
+
+ this.localName = localName;
+ this.namespaceURI = namespaceURI;
+ }
+
+ // for DeferredElementImpl
+ protected ElementNSImpl(CoreDocumentImpl ownerDocument,
+ String value) {
+ super(ownerDocument, value);
+ }
+
+ // Support for DOM Level 3 renameNode method.
+ // Note: This only deals with part of the pb. CoreDocumentImpl
+ // does all the work.
+ void rename(String namespaceURI, String qualifiedName)
+ {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ this.name = qualifiedName;
+ setName(namespaceURI, qualifiedName);
+ reconcileDefaultAttributes();
+ }
+
+ //
+ // Node methods
+ //
+
+
+
+ //
+ //DOM2: Namespace methods.
+ //
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * The namespace URI of this node, or null if it is unspecified.
+ *
+ * This is not a computed value that is the result of a namespace lookup based on
+ * an examination of the namespace declarations in scope. It is merely the
+ * namespace URI given at creation time.
+ *
+ * For nodes created with a DOM Level 1 method, such as createElement
+ * from the Document interface, this is null.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public String getNamespaceURI()
+ {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return namespaceURI;
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * The namespace prefix of this node, or null if it is unspecified.
+ *
+ * For nodes created with a DOM Level 1 method, such as createElement
+ * from the Document interface, this is null.
+ *
+ * @since WD-DOM-Level-2-19990923
+ */
+ public String getPrefix()
+ {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ int index = name.indexOf(':');
+ return index < 0 ? null : name.substring(0, index);
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Note that setting this attribute changes the nodeName attribute, which holds the
+ * qualified name, as well as the tagName and name attributes of the Element
+ * and Attr interfaces, when applicable.
+ *
+ * @param prefix The namespace prefix of this node, or null(empty string) if it is unspecified.
+ *
+ * @exception INVALID_CHARACTER_ERR
+ * Raised if the specified
+ * prefix contains an invalid character.
+ * @exception DOMException
+ * @since WD-DOM-Level-2-19990923
+ */
+ public void setPrefix(String prefix)
+ throws DOMException
+ {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (ownerDocument.errorChecking) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
+ }
+ if (prefix != null && prefix.length() != 0) {
+ if (!CoreDocumentImpl.isXMLName(prefix,ownerDocument.isXML11Version())) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
+ }
+ if (namespaceURI == null || prefix.indexOf(':') >=0) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ } else if (prefix.equals("xml")) {
+ if (!namespaceURI.equals(xmlURI)) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ }
+ }
+
+ }
+ // update node name with new qualifiedName
+ if (prefix !=null && prefix.length() != 0) {
+ name = prefix + ":" + localName;
+ }
+ else {
+ name = localName;
+ }
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Returns the local part of the qualified name of this node.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public String getLocalName()
+ {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return localName;
+ }
+
+ /**
+ * NON-DOM
+ * Returns the xml:base attribute.
+ */
+ protected Attr getXMLBaseAttribute() {
+ return (Attr) attributes.getNamedItemNS("http://www.w3.org/XML/1998/namespace", "base");
+ } // getXMLBaseAttribute():Attr
+
+ /**
+ * @see org.w3c.dom.TypeInfo#getTypeName()
+ */
+ public String getTypeName() {
+ if (type !=null){
+ if (type instanceof XSSimpleTypeDecl) {
+ return ((XSSimpleTypeDecl) type).getTypeName();
+ } else if (type instanceof XSComplexTypeDecl) {
+ return ((XSComplexTypeDecl) type).getTypeName();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @see org.w3c.dom.TypeInfo#getTypeNamespace()
+ */
+ public String getTypeNamespace() {
+ if (type !=null){
+ return type.getNamespace();
+ }
+ return null;
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ * Checks if a type is derived from another by restriction. See:
+ * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
+ *
+ * @param typeNamespaceArg
+ * The namspace of the ancestor type declaration
+ * @param typeNameArg
+ * The name of the ancestor type declaration
+ * @param derivationMethod
+ * The derivation method
+ *
+ * @return boolean True if the type is derived by restriciton for the
+ * reference type
+ */
+ public boolean isDerivedFrom(String typeNamespaceArg, String typeNameArg,
+ int derivationMethod) {
+ if(needsSyncData()) {
+ synchronizeData();
+ }
+ if (type != null) {
+ if (type instanceof XSSimpleTypeDecl) {
+ return ((XSSimpleTypeDecl) type).isDOMDerivedFrom(
+ typeNamespaceArg, typeNameArg, derivationMethod);
+ } else if (type instanceof XSComplexTypeDecl) {
+ return ((XSComplexTypeDecl) type).isDOMDerivedFrom(
+ typeNamespaceArg, typeNameArg, derivationMethod);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * NON-DOM: setting type used by the DOM parser
+ * @see NodeImpl#setReadOnly
+ */
+ public void setType(XSTypeDefinition type) {
+ this.type = type;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/EntityImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/EntityImpl.java
new file mode 100644
index 0000000..7921d9a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/EntityImpl.java
@@ -0,0 +1,340 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.Entity;
+import org.w3c.dom.Node;
+
+/**
+ * Entity nodes hold the reference data for an XML Entity -- either
+ * parsed or unparsed. The nodeName (inherited from Node) will contain
+ * the name (if any) of the Entity. Its data will be contained in the
+ * Entity's children, in exactly the structure which an
+ * EntityReference to this name will present within the document's
+ * body.
+ *
+ * Note that this object models the actual entity, _not_ the entity
+ * declaration or the entity reference.
+ *
+ * An XML processor may choose to completely expand entities before
+ * the structure model is passed to the DOM; in this case, there will
+ * be no EntityReferences in the DOM tree.
+ *
+ * Quoting the 10/01 DOM Proposal,
+ *
+ * "The DOM Level 1 does not support editing Entity nodes; if a user
+ * wants to make changes to the contents of an Entity, every related
+ * EntityReference node has to be replaced in the structure model by
+ * a clone of the Entity's contents, and then the desired changes
+ * must be made to each of those clones instead. All the
+ * descendants of an Entity node are readonly."
+ *
+ * I'm interpreting this as: It is the parser's responsibilty to call
+ * the non-DOM operation setReadOnly(true,true) after it constructs
+ * the Entity. Since the DOM explicitly decided not to deal with this,
+ * _any_ answer will involve a non-DOM operation, and this is the
+ * simplest solution.
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani, IBM
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class EntityImpl
+ extends ParentNode
+ implements Entity {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -3575760943444303423L;
+
+ //
+ // Data
+ //
+
+ /** Entity name. */
+ protected String name;
+
+ /** Public identifier. */
+ protected String publicId;
+
+ /** System identifier. */
+ protected String systemId;
+
+ /** Encoding */
+ protected String encoding;
+
+
+ /** Input Encoding */
+ protected String inputEncoding;
+
+ /** Version */
+ protected String version;
+
+
+ /** Notation name. */
+ protected String notationName;
+
+ /** base uri*/
+ protected String baseURI;
+
+ //
+ // Constructors
+ //
+
+ /** Factory constructor. */
+ public EntityImpl(CoreDocumentImpl ownerDoc, String name) {
+ super(ownerDoc);
+ this.name = name;
+ isReadOnly(true);
+ }
+
+ //
+ // Node methods
+ //
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public short getNodeType() {
+ return Node.ENTITY_NODE;
+ }
+
+ /**
+ * Returns the entity name
+ */
+ public String getNodeName() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return name;
+ }
+
+ /** Clone node. */
+ public Node cloneNode(boolean deep) {
+ EntityImpl newentity = (EntityImpl)super.cloneNode(deep);
+ newentity.setReadOnly(true, deep);
+ return newentity;
+ }
+
+ //
+ // Entity methods
+ //
+
+ /**
+ * The public identifier associated with the entity. If not specified,
+ * this will be null.
+ */
+ public String getPublicId() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return publicId;
+
+ } // getPublicId():String
+
+ /**
+ * The system identifier associated with the entity. If not specified,
+ * this will be null.
+ */
+ public String getSystemId() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return systemId;
+
+ } // getSystemId():String
+
+ /**
+ * DOM Level 3 WD - experimental
+ * the version number of this entity, when it is an external parsed entity.
+ */
+ public String getXmlVersion() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return version;
+
+ } // getVersion():String
+
+
+ /**
+ * DOM Level 3 WD - experimental
+ * the encoding of this entity, when it is an external parsed entity.
+ */
+ public String getXmlEncoding() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ return encoding;
+
+ } // getVersion():String
+
+
+
+
+
+ /**
+ * Unparsed entities -- which contain non-XML data -- have a
+ * "notation name" which tells applications how to deal with them.
+ * Parsed entities, which are in XML format, don't need this and
+ * set it to null.
+ */
+ public String getNotationName() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return notationName;
+
+ } // getNotationName():String
+
+ //
+ // Public methods
+ //
+
+ /**
+ * DOM Level 2: The public identifier associated with the entity. If not specified,
+ * this will be null. */
+ public void setPublicId(String id) {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ publicId = id;
+
+ } // setPublicId(String)
+
+ /**
+ * NON-DOM
+ * encoding - An attribute specifying, as part of the text declaration,
+ * the encoding of this entity, when it is an external parsed entity.
+ * This is null otherwise
+ *
+ */
+ public void setXmlEncoding(String value) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ encoding = value;
+ } // setEncoding (String)
+
+
+ /**
+ * An attribute specifying the encoding used for this entity at the tiome
+ * of parsing, when it is an external parsed entity. This is
+ * null if it an entity from the internal subset or if it
+ * is not known..
+ * @since DOM Level 3
+ */
+ public String getInputEncoding(){
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return inputEncoding;
+ }
+
+ /**
+ * NON-DOM, used to set the input encoding.
+ */
+ public void setInputEncoding(String inputEncoding){
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ this.inputEncoding = inputEncoding;
+ }
+
+ /**
+ * NON-DOM
+ * version - An attribute specifying, as part of the text declaration,
+ * the version number of this entity, when it is an external parsed entity.
+ * This is null otherwise
+ */
+ public void setXmlVersion(String value) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ version = value;
+ } // setVersion (String)
+
+
+ /**
+ * DOM Level 2: The system identifier associated with the entity. If not
+ * specified, this will be null.
+ */
+ public void setSystemId(String id) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ systemId = id;
+
+ } // setSystemId(String)
+
+ /**
+ * DOM Level 2: Unparsed entities -- which contain non-XML data -- have a
+ * "notation name" which tells applications how to deal with them.
+ * Parsed entities, which are in XML format, don't need this and
+ * set it to null.
+ */
+ public void setNotationName(String name) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ notationName = name;
+
+ } // setNotationName(String)
+
+
+
+ /**
+ * Returns the absolute base URI of this node or null if the implementation
+ * wasn't able to obtain an absolute URI. Note: If the URI is malformed, a
+ * null is returned.
+ *
+ * @return The absolute base URI of this node or null.
+ * @since DOM Level 3
+ */
+ public String getBaseURI() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return (baseURI!=null)?baseURI:((CoreDocumentImpl)getOwnerDocument()).getBaseURI();
+ }
+
+ /** NON-DOM: set base uri*/
+ public void setBaseURI(String uri){
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ baseURI = uri;
+ }
+
+
+
+} // class EntityImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/EntityReferenceImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/EntityReferenceImpl.java
new file mode 100644
index 0000000..8b424d9
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/EntityReferenceImpl.java
@@ -0,0 +1,400 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.apache.xerces.util.URI;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * EntityReference models the XML &entityname; syntax, when used for
+ * entities defined by the DOM. Entities hardcoded into XML, such as
+ * character entities, should instead have been translated into text
+ * by the code which generated the DOM tree.
+ *
+ * An XML processor has the alternative of fully expanding Entities
+ * into the normal document tree. If it does so, no EntityReference nodes
+ * will appear.
+ *
+ * Similarly, non-validating XML processors are not required to read
+ * or process entity declarations made in the external subset or
+ * declared in external parameter entities. Hence, some applications
+ * may not make the replacement value available for Parsed Entities
+ * of these types.
+ *
+ * EntityReference behaves as a read-only node, and the children of
+ * the EntityReference (which reflect those of the Entity, and should
+ * also be read-only) give its replacement value, if any. They are
+ * supposed to automagically stay in synch if the DocumentType is
+ * updated with new values for the Entity.
+ *
+ * The defined behavior makes efficient storage difficult for the DOM
+ * implementor. We can't just look aside to the Entity's definition
+ * in the DocumentType since those nodes have the wrong parent (unless
+ * we can come up with a clever "imaginary parent" mechanism). We
+ * must at least appear to clone those children... which raises the
+ * issue of keeping the reference synchronized with its parent.
+ * This leads me back to the "cached image of centrally defined data"
+ * solution, much as I dislike it.
+ *
+ * For now I have decided, since REC-DOM-Level-1-19980818 doesn't
+ * cover this in much detail, that synchronization doesn't have to be
+ * considered while the user is deep in the tree. That is, if you're
+ * looking within one of the EntityReferennce's children and the Entity
+ * changes, you won't be informed; instead, you will continue to access
+ * the same object -- which may or may not still be part of the tree.
+ * This is the same behavior that obtains elsewhere in the DOM if the
+ * subtree you're looking at is deleted from its parent, so it's
+ * acceptable here. (If it really bothers folks, we could set things
+ * up so deleted subtrees are walked and marked invalid, but that's
+ * not part of the DOM's defined behavior.)
+ *
+ * As a result, only the EntityReference itself has to be aware of
+ * changes in the Entity. And it can take advantage of the same
+ * structure-change-monitoring code I implemented to support
+ * DeepNodeList.
+ *
+ * @xerces.internal
+ *
+ * @author Arnaud Le Hors, IBM
+ * @author Joe Kesselman, IBM
+ * @author Andy Clark, IBM
+ * @author Ralf Pfeiffer, IBM
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class EntityReferenceImpl
+extends ParentNode
+implements EntityReference {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -7381452955687102062L;
+
+ //
+ // Data
+ //
+
+ /** Name of Entity referenced */
+ protected String name;
+ /** Base URI*/
+ protected String baseURI;
+
+
+ /** Entity changes. */
+ //protected int entityChanges = -1;
+
+ /** Enable synchronize. */
+ //protected boolean fEnableSynchronize = false;
+
+ //
+ // Constructors
+ //
+
+ /** Factory constructor. */
+ public EntityReferenceImpl(CoreDocumentImpl ownerDoc, String name) {
+ super(ownerDoc);
+ this.name = name;
+ isReadOnly(true);
+ needsSyncChildren(true);
+ }
+
+ //
+ // Node methods
+ //
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public short getNodeType() {
+ return Node.ENTITY_REFERENCE_NODE;
+ }
+
+ /**
+ * Returns the name of the entity referenced
+ */
+ public String getNodeName() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return name;
+ }
+
+ /** Clone node. */
+ public Node cloneNode(boolean deep) {
+ EntityReferenceImpl er = (EntityReferenceImpl)super.cloneNode(deep);
+ er.setReadOnly(true, deep);
+ return er;
+ }
+
+ /**
+ * Returns the absolute base URI of this node or null if the implementation
+ * wasn't able to obtain an absolute URI. Note: If the URI is malformed, a
+ * null is returned.
+ *
+ * @return The absolute base URI of this node or null.
+ * @since DOM Level 3
+ */
+ public String getBaseURI() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (baseURI == null) {
+ DocumentType doctype;
+ NamedNodeMap entities;
+ EntityImpl entDef;
+ if (null != (doctype = getOwnerDocument().getDoctype()) &&
+ null != (entities = doctype.getEntities())) {
+
+ entDef = (EntityImpl)entities.getNamedItem(getNodeName());
+ if (entDef !=null) {
+ return entDef.getBaseURI();
+ }
+ }
+ } else if (baseURI != null && baseURI.length() != 0 ) {// attribute value is always empty string
+ try {
+ return new URI(baseURI).toString();
+ }
+ catch (org.apache.xerces.util.URI.MalformedURIException e){
+ // REVISIT: what should happen in this case?
+ return null;
+ }
+ }
+ return baseURI;
+ }
+
+
+ /** NON-DOM: set base uri*/
+ public void setBaseURI(String uri){
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ baseURI = uri;
+ }
+
+ /**
+ * NON-DOM: compute string representation of the entity reference.
+ * This method is used to retrieve a string value for an attribute node that has child nodes.
+ * @return String representing a value of this entity ref. or
+ * null if any node other than EntityReference, Text is encountered
+ * during computation
+ */
+ protected String getEntityRefValue (){
+ if (needsSyncChildren()){
+ synchronizeChildren();
+ }
+
+ String value = "";
+ if (firstChild != null){
+ if (firstChild.getNodeType() == Node.ENTITY_REFERENCE_NODE){
+ value = ((EntityReferenceImpl)firstChild).getEntityRefValue();
+ }
+ else if (firstChild.getNodeType() == Node.TEXT_NODE){
+ value = firstChild.getNodeValue();
+ }
+ else {
+ // invalid to have other types of nodes in attr value
+ return null;
+ }
+
+ if (firstChild.nextSibling == null){
+ return value;
+ }
+ else {
+ StringBuffer buff = new StringBuffer(value);
+ ChildNode next = firstChild.nextSibling;
+ while (next != null){
+
+ if (next.getNodeType() == Node.ENTITY_REFERENCE_NODE){
+ value = ((EntityReferenceImpl)next).getEntityRefValue();
+ }
+ else if (next.getNodeType() == Node.TEXT_NODE){
+ value = next.getNodeValue();
+ }
+ else {
+ // invalid to have other types of nodes in attr value
+ return null;
+ }
+ buff.append(value);
+ next = next.nextSibling;
+
+ }
+ return buff.toString();
+ }
+ }
+ return "";
+ }
+
+ /**
+ * EntityReference's children are a reflection of those defined in the
+ * named Entity. This method creates them if they haven't been created yet.
+ * This doesn't support editing the Entity though, since this only called
+ * once for all.
+ */
+ protected void synchronizeChildren() {
+ // no need to synchronize again
+ needsSyncChildren(false);
+
+ DocumentType doctype;
+ NamedNodeMap entities;
+ EntityImpl entDef;
+ if (null != (doctype = getOwnerDocument().getDoctype()) &&
+ null != (entities = doctype.getEntities())) {
+
+ entDef = (EntityImpl)entities.getNamedItem(getNodeName());
+
+ // No Entity by this name, stop here.
+ if (entDef == null)
+ return;
+
+ // If entity's definition exists, clone its kids
+ isReadOnly(false);
+ for (Node defkid = entDef.getFirstChild();
+ defkid != null;
+ defkid = defkid.getNextSibling()) {
+ Node newkid = defkid.cloneNode(true);
+ insertBefore(newkid, null);
+ }
+ setReadOnly(true, true);
+ }
+ }
+
+
+ /**
+ * NON-DOM: sets the node and its children value.
+ *
+ * Note: make sure that entity reference and its kids could be set readonly.
+ */
+ public void setReadOnly(boolean readOnly, boolean deep) {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (deep) {
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ // Recursively set kids
+ for (ChildNode mykid = firstChild;
+ mykid != null;
+ mykid = mykid.nextSibling) {
+
+ mykid.setReadOnly(readOnly,true);
+
+ }
+ }
+ isReadOnly(readOnly);
+ } // setReadOnly(boolean,boolean)
+
+
+ /**
+ * Enable the synchronize method which may do cloning. This method is enabled
+ * when the parser is done with an EntityReference.
+ /***
+ // revisit: enable editing of Entity
+ public void enableSynchronize(boolean enableSynchronize) {
+ fEnableSynchronize= enableSynchronize;
+ }
+ /***/
+
+ /**
+ * EntityReference's children are a reflection of those defined in the
+ * named Entity. This method updates them if the Entity is changed.
+ *
+ * It is unclear what the least-cost resynch mechanism is.
+ * If we expect the kids to be shallow, and/or expect changes
+ * to the Entity contents to be rare, wiping them all out
+ * and recloning is simplest.
+ *
+ * If we expect them to be deep,
+ * it might be better to first decide which kids (if any)
+ * persist, and keep the ones (if any) that are unchanged
+ * rather than doing all the work of cloning them again.
+ * But that latter gets into having to convolve the two child lists,
+ * insert new information in the right order (and possibly reorder
+ * the existing kids), and a few other complexities that I really
+ * don't want to deal with in this implementation.
+ *
+ * Note that if we decide that we need to update the EntityReference's
+ * contents, we have to turn off the readOnly flag temporarily to do so.
+ * When we get around to adding multitasking support, this whole method
+ * should probably be an atomic operation.
+ *
+ * @see DocumentTypeImpl
+ * @see EntityImpl
+ */
+ // The Xerces parser invokes callbacks for startEnityReference
+ // the parsed value of the entity EACH TIME, so it is actually
+ // easier to create the nodes through the callbacks rather than
+ // clone the Entity.
+ /***
+ // revisit: enable editing of Entity
+ private void synchronize() {
+ if (!fEnableSynchronize) {
+ return;
+ }
+ DocumentType doctype;
+ NamedNodeMap entities;
+ EntityImpl entDef;
+ if (null != (doctype = getOwnerDocument().getDoctype()) &&
+ null != (entities = doctype.getEntities())) {
+
+ entDef = (EntityImpl)entities.getNamedItem(getNodeName());
+
+ // No Entity by this name. If we had a change count, reset it.
+ if(null==entDef)
+ entityChanges=-1;
+
+ // If no kids availalble, wipe any pre-existing children.
+ // (See discussion above.)
+ // Note that we have to use the superclass to avoid recursion
+ // through Synchronize.
+ readOnly=false;
+ if(null==entDef || !entDef.hasChildNodes())
+ for(Node kid=super.getFirstChild();
+ kid!=null;
+ kid=super.getFirstChild())
+ removeChild(kid);
+
+ // If entity's definition changed, clone its kids
+ // (See discussion above.)
+ if(null!=entDef && entDef.changes!=entityChanges) {
+ for(Node defkid=entDef.getFirstChild();
+ defkid!=null;
+ defkid=defkid.getNextSibling()) {
+
+ NodeImpl newkid=(NodeImpl) defkid.cloneNode(true);
+ newkid.setReadOnly(true,true);
+ insertBefore(newkid,null);
+ }
+ entityChanges=entDef.changes;
+ }
+ readOnly=true;
+ }
+ }
+ /***/
+
+
+} // class EntityReferenceImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/LCount.java b/resources/xerces2-j-src/org/apache/xerces/dom/LCount.java
new file mode 100644
index 0000000..313a29b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/LCount.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.xerces.dom;
+
+
+/** Internal class LCount is used to track the number of
+ listeners registered for a given event name, as an entry
+ in a global hashtable. This should allow us to avoid generating,
+ or discard, events for which no listeners are registered.
+
+ ***** There should undoubtedly be methods here to manipulate
+ this table. At the moment that code's residing in NodeImpl.
+ Move it when we have a chance to do so. Sorry; we were
+ rushed.
+
+ ???? CONCERN: Hashtables are known to be "overserialized" in
+ current versions of Java. That may impact performance.
+
+ ???? CONCERN: The hashtable should probably be a per-document object.
+ Finer granularity would be even better, but would cost more cycles to
+ resolve and might not save enough event traffic to be worth the investment.
+*/
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+
+class LCount
+{
+ static java.util.Hashtable lCounts=new java.util.Hashtable();
+ public int captures=0,bubbles=0,defaults, total=0;
+
+ static LCount lookup(String evtName)
+ {
+ LCount lc=(LCount)lCounts.get(evtName);
+ if(lc==null)
+ lCounts.put(evtName,(lc=new LCount()));
+ return lc;
+ }
+} // class LCount
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/NamedNodeMapImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/NamedNodeMapImpl.java
new file mode 100644
index 0000000..23a9f22
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/NamedNodeMapImpl.java
@@ -0,0 +1,628 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * NamedNodeMaps represent collections of Nodes that can be accessed
+ * by name. Entity and Notation nodes are stored in NamedNodeMaps
+ * attached to the DocumentType. Attributes are placed in a NamedNodeMap
+ * attached to the elem they're related too. However, because attributes
+ * require more work, such as firing mutation events, they are stored in
+ * a subclass of NamedNodeMapImpl.
+ *
+ * Only one Node may be stored per name; attempting to
+ * store another will replace the previous value.
+ *
+ * NOTE: The "primary" storage key is taken from the NodeName attribute of the
+ * node. The "secondary" storage key is the namespaceURI and localName, when
+ * accessed by DOM level 2 nodes. All nodes, even DOM Level 2 nodes are stored
+ * in a single ArrayList sorted by the primary "nodename" key.
+ *
+ * NOTE: item()'s integer index does _not_ imply that the named nodes
+ * must be stored in an array; that's only an access method. Note too
+ * that these indices are "live"; if someone changes the map's
+ * contents, the indices associated with nodes may change.
+ *
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class NamedNodeMapImpl
+ implements NamedNodeMap, Serializable {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -7039242451046758020L;
+
+ //
+ // Data
+ //
+
+ protected short flags;
+
+ protected final static short READONLY = 0x1<<0;
+ protected final static short CHANGED = 0x1<<1;
+ protected final static short HASDEFAULTS = 0x1<<2;
+
+ /** Nodes. */
+ protected List nodes;
+
+ protected NodeImpl ownerNode; // the node this map belongs to
+
+ //
+ // Constructors
+ //
+
+ /** Constructs a named node map. */
+ protected NamedNodeMapImpl(NodeImpl ownerNode) {
+ this.ownerNode = ownerNode;
+ }
+
+ //
+ // NamedNodeMap methods
+ //
+
+ /**
+ * Report how many nodes are currently stored in this NamedNodeMap.
+ * Caveat: This is a count rather than an index, so the
+ * highest-numbered node at any time can be accessed via
+ * item(getLength()-1).
+ */
+ public int getLength() {
+ return (nodes != null) ? nodes.size() : 0;
+ }
+
+ /**
+ * Retrieve an item from the map by 0-based index.
+ *
+ * @param index Which item to retrieve. Note that indices are just an
+ * enumeration of the current contents; they aren't guaranteed to be
+ * stable, nor do they imply any promises about the order of the
+ * NamedNodeMap's contents. In other words, DO NOT assume either that
+ * index(i) will always refer to the same entry, or that there is any
+ * stable ordering of entries... and be prepared for double-reporting
+ * or skips as insertion and deletion occur.
+ *
+ * @return the node which currenly has the specified index, or null if index
+ * is greater than or equal to getLength().
+ */
+ public Node item(int index) {
+ return (nodes != null && index < nodes.size()) ?
+ (Node)(nodes.get(index)) : null;
+ }
+
+ /**
+ * Retrieve a node by name.
+ *
+ * @param name Name of a node to look up.
+ * @return the Node (of unspecified sub-class) stored with that name, or
+ * null if no value has been assigned to that name.
+ */
+ public Node getNamedItem(String name) {
+
+ int i = findNamePoint(name,0);
+ return (i < 0) ? null : (Node)(nodes.get(i));
+
+ } // getNamedItem(String):Node
+
+ /**
+ * Introduced in DOM Level 2.
+ * Retrieves a node specified by local name and namespace URI.
+ *
+ * @param namespaceURI The namespace URI of the node to retrieve.
+ * When it is null or an empty string, this
+ * method behaves like getNamedItem.
+ * @param localName The local name of the node to retrieve.
+ * @return Node A Node (of any type) with the specified name, or null if the specified
+ * name did not identify any node in the map.
+ */
+ public Node getNamedItemNS(String namespaceURI, String localName) {
+
+ int i = findNamePoint(namespaceURI, localName);
+ return (i < 0) ? null : (Node)(nodes.get(i));
+
+ } // getNamedItemNS(String,String):Node
+
+ /**
+ * Adds a node using its nodeName attribute.
+ * As the nodeName attribute is used to derive the name which the node must be
+ * stored under, multiple nodes of certain types (those that have a "special" string
+ * value) cannot be stored as the names would clash. This is seen as preferable to
+ * allowing nodes to be aliased.
+ * @see org.w3c.dom.NamedNodeMap#setNamedItem
+ * @return If the new Node replaces an existing node the replaced Node is returned,
+ * otherwise null is returned.
+ * @param arg
+ * A node to store in a named node map. The node will later be
+ * accessible using the value of the namespaceURI and localName
+ * attribute of the node. If a node with those namespace URI and
+ * local name is already present in the map, it is replaced by the new
+ * one.
+ * @exception org.w3c.dom.DOMException The exception description.
+ */
+ public Node setNamedItem(Node arg)
+ throws DOMException {
+
+ CoreDocumentImpl ownerDocument = ownerNode.ownerDocument();
+ if (ownerDocument.errorChecking) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+ if (arg.getOwnerDocument() != ownerDocument) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+ }
+ }
+
+ int i = findNamePoint(arg.getNodeName(),0);
+ NodeImpl previous = null;
+ if (i >= 0) {
+ previous = (NodeImpl) nodes.get(i);
+ nodes.set(i, arg);
+ } else {
+ i = -1 - i; // Insert point (may be end of list)
+ if (null == nodes) {
+ nodes = new ArrayList(5);
+ }
+ nodes.add(i, arg);
+ }
+ return previous;
+
+ } // setNamedItem(Node):Node
+
+ /**
+ * Adds a node using its namespaceURI and localName.
+ * @see org.w3c.dom.NamedNodeMap#setNamedItem
+ * @return If the new Node replaces an existing node the replaced Node is returned,
+ * otherwise null is returned.
+ * @param arg A node to store in a named node map. The node will later be
+ * accessible using the value of the namespaceURI and localName
+ * attribute of the node. If a node with those namespace URI and
+ * local name is already present in the map, it is replaced by the new
+ * one.
+ */
+ public Node setNamedItemNS(Node arg)
+ throws DOMException {
+
+ CoreDocumentImpl ownerDocument = ownerNode.ownerDocument();
+ if (ownerDocument.errorChecking) {
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
+
+ if(arg.getOwnerDocument() != ownerDocument) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+ }
+ }
+
+ int i = findNamePoint(arg.getNamespaceURI(), arg.getLocalName());
+ NodeImpl previous = null;
+ if (i >= 0) {
+ previous = (NodeImpl) nodes.get(i);
+ nodes.set(i, arg);
+ } else {
+ // If we can't find by namespaceURI, localName, then we find by
+ // nodeName so we know where to insert.
+ i = findNamePoint(arg.getNodeName(),0);
+ if (i >= 0) {
+ previous = (NodeImpl) nodes.get(i);
+ nodes.add(i, arg);
+ } else {
+ i = -1 - i; // Insert point (may be end of list)
+ if (null == nodes) {
+ nodes = new ArrayList(5);
+ }
+ nodes.add(i, arg);
+ }
+ }
+ return previous;
+
+ } // setNamedItemNS(Node):Node
+
+ /**
+ * Removes a node specified by name.
+ * @param name The name of a node to remove.
+ * @return The node removed from the map if a node with such a name exists.
+ */
+ /***/
+ public Node removeNamedItem(String name)
+ throws DOMException {
+
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw
+ new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
+ }
+ int i = findNamePoint(name,0);
+ if (i < 0) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+
+ NodeImpl n = (NodeImpl)nodes.get(i);
+ nodes.remove(i);
+
+ return n;
+
+ } // removeNamedItem(String):Node
+
+ /**
+ * Introduced in DOM Level 2.
+ * Removes a node specified by local name and namespace URI.
+ * @param namespaceURI
+ * The namespace URI of the node to remove.
+ * When it is null or an empty string, this
+ * method behaves like removeNamedItem.
+ * @param name The local name of the node to remove.
+ * @return Node The node removed from the map if a node with such
+ * a local name and namespace URI exists.
+ * @throws NOT_FOUND_ERR: Raised if there is no node named
+ * name in the map.
+
+ */
+ public Node removeNamedItemNS(String namespaceURI, String name)
+ throws DOMException {
+
+ if (isReadOnly()) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ throw
+ new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
+ }
+ int i = findNamePoint(namespaceURI, name);
+ if (i < 0) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
+ }
+
+ NodeImpl n = (NodeImpl)nodes.get(i);
+ nodes.remove(i);
+
+ return n;
+
+ } // removeNamedItem(String):Node
+
+ //
+ // Public methods
+ //
+
+ /**
+ * Cloning a NamedNodeMap is a DEEP OPERATION; it always clones
+ * all the nodes contained in the map.
+ */
+
+ public NamedNodeMapImpl cloneMap(NodeImpl ownerNode) {
+ NamedNodeMapImpl newmap = new NamedNodeMapImpl(ownerNode);
+ newmap.cloneContent(this);
+ return newmap;
+ }
+
+ protected void cloneContent(NamedNodeMapImpl srcmap) {
+ List srcnodes = srcmap.nodes;
+ if (srcnodes != null) {
+ int size = srcnodes.size();
+ if (size != 0) {
+ if (nodes == null) {
+ nodes = new ArrayList(size);
+ }
+ else {
+ nodes.clear();
+ }
+ for (int i = 0; i < size; ++i) {
+ NodeImpl n = (NodeImpl) srcmap.nodes.get(i);
+ NodeImpl clone = (NodeImpl) n.cloneNode(true);
+ clone.isSpecified(n.isSpecified());
+ nodes.add(clone);
+ }
+ }
+ }
+ } // cloneMap():NamedNodeMapImpl
+
+ //
+ // Package methods
+ //
+
+ /**
+ * Internal subroutine to allow read-only Nodes to make their contained
+ * NamedNodeMaps readonly too. I expect that in fact the shallow
+ * version of this operation will never be
+ *
+ * @param readOnly boolean true to make read-only, false to permit editing.
+ * @param deep boolean true to pass this request along to the contained
+ * nodes, false to only toggle the NamedNodeMap itself. I expect that
+ * the shallow version of this operation will never be used, but I want
+ * to design it in now, while I'm thinking about it.
+ */
+ void setReadOnly(boolean readOnly, boolean deep) {
+ isReadOnly(readOnly);
+ if (deep && nodes != null) {
+ for (int i = nodes.size() - 1; i >= 0; i--) {
+ ((NodeImpl) nodes.get(i)).setReadOnly(readOnly,deep);
+ }
+ }
+ } // setReadOnly(boolean,boolean)
+
+ /**
+ * Internal subroutine returns this NodeNameMap's (shallow) readOnly value.
+ *
+ */
+ boolean getReadOnly() {
+ return isReadOnly();
+ } // getReadOnly()
+
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * NON-DOM
+ * set the ownerDocument of this node, and the attributes it contains
+ */
+ protected void setOwnerDocument(CoreDocumentImpl doc) {
+ if (nodes != null) {
+ final int size = nodes.size();
+ for (int i = 0; i < size; ++i) {
+ ((NodeImpl)item(i)).setOwnerDocument(doc);
+ }
+ }
+ }
+
+ final boolean isReadOnly() {
+ return (flags & READONLY) != 0;
+ }
+
+ final void isReadOnly(boolean value) {
+ flags = (short) (value ? flags | READONLY : flags & ~READONLY);
+ }
+
+ final boolean changed() {
+ return (flags & CHANGED) != 0;
+ }
+
+ final void changed(boolean value) {
+ flags = (short) (value ? flags | CHANGED : flags & ~CHANGED);
+ }
+
+ final boolean hasDefaults() {
+ return (flags & HASDEFAULTS) != 0;
+ }
+
+ final void hasDefaults(boolean value) {
+ flags = (short) (value ? flags | HASDEFAULTS : flags & ~HASDEFAULTS);
+ }
+
+ //
+ // Private methods
+ //
+
+ /**
+ * Subroutine: Locate the named item, or the point at which said item
+ * should be added.
+ *
+ * @param name Name of a node to look up.
+ *
+ * @return If positive or zero, the index of the found item.
+ * If negative, index of the appropriate point at which to insert
+ * the item, encoded as -1-index and hence reconvertable by subtracting
+ * it from -1. (Encoding because I don't want to recompare the strings
+ * but don't want to burn bytes on a datatype to hold a flagged value.)
+ */
+ protected int findNamePoint(String name, int start) {
+
+ // Binary search
+ int i = 0;
+ if (nodes != null) {
+ int first = start;
+ int last = nodes.size() - 1;
+
+ while (first <= last) {
+ i = (first + last) / 2;
+ int test = name.compareTo(((Node)(nodes.get(i))).getNodeName());
+ if (test == 0) {
+ return i; // Name found
+ }
+ else if (test < 0) {
+ last = i - 1;
+ }
+ else {
+ first = i + 1;
+ }
+ }
+
+ if (first > i) {
+ i = first;
+ }
+ }
+
+ return -1 - i; // not-found has to be encoded.
+
+ } // findNamePoint(String):int
+
+
+ /** This findNamePoint is for DOM Level 2 Namespaces.
+ */
+ protected int findNamePoint(String namespaceURI, String name) {
+
+ if (nodes == null) return -1;
+ if (name == null) return -1;
+
+ // This is a linear search through the same nodes ArrayList.
+ // The ArrayList is sorted on the DOM Level 1 nodename.
+ // The DOM Level 2 NS keys are namespaceURI and Localname,
+ // so we must linear search thru it.
+ // In addition, to get this to work with nodes without any namespace
+ // (namespaceURI and localNames are both null) we then use the nodeName
+ // as a secondary key.
+ final int size = nodes.size();
+ for (int i = 0; i < size; ++i) {
+ NodeImpl a = (NodeImpl)nodes.get(i);
+ String aNamespaceURI = a.getNamespaceURI();
+ String aLocalName = a.getLocalName();
+ if (namespaceURI == null) {
+ if (aNamespaceURI == null
+ &&
+ (name.equals(aLocalName)
+ ||
+ (aLocalName == null && name.equals(a.getNodeName()))))
+ return i;
+ } else {
+ if (namespaceURI.equals(aNamespaceURI)
+ &&
+ name.equals(aLocalName))
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ // compare 2 nodes in the map. If a precedes b, return true, otherwise
+ // return false
+ protected boolean precedes(Node a, Node b) {
+
+ if (nodes != null) {
+ final int size = nodes.size();
+ for (int i = 0; i < size; ++i) {
+ Node n = (Node)nodes.get(i);
+ if (n==a) return true;
+ if (n==b) return false;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * NON-DOM: Remove attribute at specified index
+ */
+ protected void removeItem(int index) {
+ if (nodes != null && index < nodes.size()){
+ nodes.remove(index);
+ }
+ }
+
+
+ protected Object getItem (int index){
+ if (nodes != null) {
+ return nodes.get(index);
+ }
+ return null;
+ }
+
+ protected int addItem (Node arg) {
+ int i = findNamePoint(arg.getNamespaceURI(), arg.getLocalName());
+ if (i >= 0) {
+ nodes.set(i, arg);
+ }
+ else {
+ // If we can't find by namespaceURI, localName, then we find by
+ // nodeName so we know where to insert.
+ i = findNamePoint(arg.getNodeName(),0);
+ if (i >= 0) {
+ nodes.add(i, arg);
+ }
+ else {
+ i = -1 - i; // Insert point (may be end of list)
+ if (null == nodes) {
+ nodes = new ArrayList(5);
+ }
+ nodes.add(i, arg);
+ }
+ }
+ return i;
+ }
+
+ /**
+ * NON-DOM: copy content of this map into the specified ArrayList
+ *
+ * @param list ArrayList to copy information into.
+ * @return A copy of this node named map
+ */
+ protected ArrayList cloneMap(ArrayList list) {
+ if (list == null) {
+ list = new ArrayList(5);
+ }
+ list.clear();
+ if (nodes != null) {
+ final int size = nodes.size();
+ for (int i = 0; i < size; ++i) {
+ list.add(nodes.get(i));
+ }
+ }
+ return list;
+ }
+
+ protected int getNamedItemIndex(String namespaceURI, String localName) {
+ return findNamePoint(namespaceURI, localName);
+ }
+
+ /**
+ * NON-DOM remove all elements from this map
+ */
+ public void removeAll (){
+ if (nodes != null) {
+ nodes.clear();
+ }
+ }
+
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ if (nodes != null) {
+ // cast to Vector is required
+ nodes = new ArrayList((Vector)nodes);
+ }
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ List oldNodes = this.nodes;
+ try {
+ if (oldNodes != null) {
+ this.nodes = new Vector(oldNodes);
+ }
+ out.defaultWriteObject();
+ }
+ // If the write fails for some reason ensure
+ // that we restore the original object.
+ finally {
+ this.nodes = oldNodes;
+ }
+ }
+
+} // class NamedNodeMapImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/NodeImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/NodeImpl.java
new file mode 100644
index 0000000..f18afe1
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/NodeImpl.java
@@ -0,0 +1,2028 @@
+ /*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Hashtable;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.UserDataHandler;
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.events.EventTarget;
+
+/**
+ * NodeImpl provides the basic structure of a DOM tree. It is never used
+ * directly, but instead is subclassed to add type and data
+ * information, and additional methods, appropriate to each node of
+ * the tree. Only its subclasses should be instantiated -- and those,
+ * with the exception of Document itself, only through a specific
+ * Document's factory methods.
+ *
+ * The Node interface provides shared behaviors such as siblings and
+ * children, both for consistancy and so that the most common tree
+ * operations may be performed without constantly having to downcast
+ * to specific node types. When there is no obvious mapping for one of
+ * these queries, it will respond with null.
+ * Note that the default behavior is that children are forbidden. To
+ * permit them, the subclass ParentNode overrides several methods.
+ *
+ * NodeImpl also implements NodeList, so it can return itself in
+ * response to the getChildNodes() query. This eliminiates the need
+ * for a separate ChildNodeList object. Note that this is an
+ * IMPLEMENTATION DETAIL; applications should _never_ assume that
+ * this identity exists.
+ *
+ * All nodes in a single document must originate
+ * in that document. (Note that this is much tighter than "must be
+ * same implementation") Nodes are all aware of their ownerDocument,
+ * and attempts to mismatch will throw WRONG_DOCUMENT_ERR.
+ *
+ * However, to save memory not all nodes always have a direct reference
+ * to their ownerDocument. When a node is owned by another node it relies
+ * on its owner to store its ownerDocument. Parent nodes always store it
+ * though, so there is never more than one level of indirection.
+ * And when a node doesn't have an owner, ownerNode refers to its
+ * ownerDocument.
+ *
+ * This class doesn't directly support mutation events, however, it still
+ * implements the EventTarget interface and forward all related calls to the
+ * document so that the document class do so.
+ *
+ * @xerces.internal
+ *
+ * @author Arnaud Le Hors, IBM
+ * @author Joe Kesselman, IBM
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public abstract class NodeImpl
+ implements Node, NodeList, EventTarget, Cloneable, Serializable{
+
+ //
+ // Constants
+ //
+
+
+ // TreePosition Constants.
+ // Taken from DOM L3 Node interface.
+ /**
+ * The node precedes the reference node.
+ */
+ public static final short TREE_POSITION_PRECEDING = 0x01;
+ /**
+ * The node follows the reference node.
+ */
+ public static final short TREE_POSITION_FOLLOWING = 0x02;
+ /**
+ * The node is an ancestor of the reference node.
+ */
+ public static final short TREE_POSITION_ANCESTOR = 0x04;
+ /**
+ * The node is a descendant of the reference node.
+ */
+ public static final short TREE_POSITION_DESCENDANT = 0x08;
+ /**
+ * The two nodes have an equivalent position. This is the case of two
+ * attributes that have the same ownerElement , and two
+ * nodes that are the same.
+ */
+ public static final short TREE_POSITION_EQUIVALENT = 0x10;
+ /**
+ * The two nodes are the same. Two nodes that are the same have an
+ * equivalent position, though the reverse may not be true.
+ */
+ public static final short TREE_POSITION_SAME_NODE = 0x20;
+ /**
+ * The two nodes are disconnected, they do not have any common ancestor.
+ * This is the case of two nodes that are not in the same document.
+ */
+ public static final short TREE_POSITION_DISCONNECTED = 0x00;
+
+
+ // DocumentPosition
+ public static final short DOCUMENT_POSITION_DISCONNECTED = 0x01;
+ public static final short DOCUMENT_POSITION_PRECEDING = 0x02;
+ public static final short DOCUMENT_POSITION_FOLLOWING = 0x04;
+ public static final short DOCUMENT_POSITION_CONTAINS = 0x08;
+ public static final short DOCUMENT_POSITION_IS_CONTAINED = 0x10;
+ public static final short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
+
+ /** Serialization version. */
+ static final long serialVersionUID = -6316591992167219696L;
+
+ // public
+
+ /** Element definition node type. */
+ public static final short ELEMENT_DEFINITION_NODE = 21;
+
+ //
+ // Data
+ //
+
+ // links
+
+ protected NodeImpl ownerNode; // typically the parent but not always!
+
+ // data
+
+ protected short flags;
+
+ protected final static short READONLY = 0x1<<0;
+ protected final static short SYNCDATA = 0x1<<1;
+ protected final static short SYNCCHILDREN = 0x1<<2;
+ protected final static short OWNED = 0x1<<3;
+ protected final static short FIRSTCHILD = 0x1<<4;
+ protected final static short SPECIFIED = 0x1<<5;
+ protected final static short IGNORABLEWS = 0x1<<6;
+ protected final static short HASSTRING = 0x1<<7;
+ protected final static short NORMALIZED = 0x1<<8;
+ protected final static short ID = 0x1<<9;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * No public constructor; only subclasses of Node should be
+ * instantiated, and those normally via a Document's factory methods
+ *
+ * Every Node knows what Document it belongs to.
+ */
+ protected NodeImpl(CoreDocumentImpl ownerDocument) {
+ // as long as we do not have any owner, ownerNode is our ownerDocument
+ ownerNode = ownerDocument;
+ } // (CoreDocumentImpl)
+
+ /** Constructor for serialization. */
+ public NodeImpl() {}
+
+ //
+ // Node methods
+ //
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public abstract short getNodeType();
+
+ /**
+ * the name of this node.
+ */
+ public abstract String getNodeName();
+
+ /**
+ * Returns the node value.
+ * @throws DOMException(DOMSTRING_SIZE_ERR)
+ */
+ public String getNodeValue()
+ throws DOMException {
+ return null; // overridden in some subclasses
+ }
+
+ /**
+ * Sets the node value.
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR)
+ */
+ public void setNodeValue(String x)
+ throws DOMException {
+ // Default behavior is to do nothing, overridden in some subclasses
+ }
+
+ /**
+ * Adds a child node to the end of the list of children for this node.
+ * Convenience shorthand for insertBefore(newChild,null).
+ * @see #insertBefore(Node, Node)
+ *
+ * By default we do not accept any children, ParentNode overrides this.
+ * @see ParentNode
+ *
+ * @return newChild, in its new state (relocated, or emptied in the case of
+ * DocumentNode.)
+ *
+ * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
+ * type that shouldn't be a child of this node.
+ *
+ * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
+ * different owner document than we do.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
+ * read-only.
+ */
+ public Node appendChild(Node newChild) throws DOMException {
+ return insertBefore(newChild, null);
+ }
+
+ /**
+ * Returns a duplicate of a given node. You can consider this a
+ * generic "copy constructor" for nodes. The newly returned object should
+ * be completely independent of the source object's subtree, so changes
+ * in one after the clone has been made will not affect the other.
+ *
+ * Note: since we never have any children deep is meaningless here,
+ * ParentNode overrides this behavior.
+ * @see ParentNode
+ *
+ *
+ * Example: Cloning a Text node will copy both the node and the text it
+ * contains.
+ *
+ * Example: Cloning something that has children -- Element or Attr, for
+ * example -- will _not_ clone those children unless a "deep clone"
+ * has been requested. A shallow clone of an Attr node will yield an
+ * empty Attr of the same name.
+ *
+ * NOTE: Clones will always be read/write, even if the node being cloned
+ * is read-only, to permit applications using only the DOM API to obtain
+ * editable copies of locked portions of the tree.
+ */
+ public Node cloneNode(boolean deep) {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ NodeImpl newnode;
+ try {
+ newnode = (NodeImpl)clone();
+ }
+ catch (CloneNotSupportedException e) {
+ // if we get here we have an error in our program we may as well
+ // be vocal about it, so that people can take appropriate action.
+ throw new RuntimeException("**Internal Error**" + e);
+ }
+
+ // Need to break the association w/ original kids
+ newnode.ownerNode = ownerDocument();
+ newnode.isOwned(false);
+
+ // By default we make all clones readwrite,
+ // this is overriden in readonly subclasses
+ newnode.isReadOnly(false);
+
+ ownerDocument().callUserDataHandlers(this, newnode,
+ UserDataHandler.NODE_CLONED);
+
+ return newnode;
+
+ } // cloneNode(boolean):Node
+
+ /**
+ * Find the Document that this Node belongs to (the document in
+ * whose context the Node was created). The Node may or may not
+ * currently be part of that Document's actual contents.
+ */
+ public Document getOwnerDocument() {
+ // if we have an owner simply forward the request
+ // otherwise ownerNode is our ownerDocument
+ if (isOwned()) {
+ return ownerNode.ownerDocument();
+ } else {
+ return (Document) ownerNode;
+ }
+ }
+
+ /**
+ * same as above but returns internal type and this one is not overridden
+ * by CoreDocumentImpl to return null
+ */
+ CoreDocumentImpl ownerDocument() {
+ // if we have an owner simply forward the request
+ // otherwise ownerNode is our ownerDocument
+ if (isOwned()) {
+ return ownerNode.ownerDocument();
+ } else {
+ return (CoreDocumentImpl) ownerNode;
+ }
+ }
+
+ /**
+ * NON-DOM
+ * set the ownerDocument of this node
+ */
+ protected void setOwnerDocument(CoreDocumentImpl doc) {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ // if we have an owner we rely on it to have it right
+ // otherwise ownerNode is our ownerDocument
+ if (!isOwned()) {
+ ownerNode = doc;
+ }
+ }
+
+ /**
+ * Returns the node number
+ */
+ protected int getNodeNumber() {
+ int nodeNumber;
+ CoreDocumentImpl cd = (CoreDocumentImpl)(this.getOwnerDocument());
+ nodeNumber = cd.getNodeNumber(this);
+ return nodeNumber;
+ }
+
+ /**
+ * Obtain the DOM-tree parent of this node, or null if it is not
+ * currently active in the DOM tree (perhaps because it has just been
+ * created or removed). Note that Document, DocumentFragment, and
+ * Attribute will never have parents.
+ */
+ public Node getParentNode() {
+ return null; // overriden by ChildNode
+ }
+
+ /*
+ * same as above but returns internal type
+ */
+ NodeImpl parentNode() {
+ return null;
+ }
+
+ /** The next child of this node's parent, or null if none */
+ public Node getNextSibling() {
+ return null; // default behavior, overriden in ChildNode
+ }
+
+ /** The previous child of this node's parent, or null if none */
+ public Node getPreviousSibling() {
+ return null; // default behavior, overriden in ChildNode
+ }
+
+ ChildNode previousSibling() {
+ return null; // default behavior, overriden in ChildNode
+ }
+
+ /**
+ * Return the collection of attributes associated with this node,
+ * or null if none. At this writing, Element is the only type of node
+ * which will ever have attributes.
+ *
+ * @see ElementImpl
+ */
+ public NamedNodeMap getAttributes() {
+ return null; // overridden in ElementImpl
+ }
+
+ /**
+ * Returns whether this node (if it is an element) has any attributes.
+ * @return true if this node has any attributes,
+ * false otherwise.
+ * @since DOM Level 2
+ * @see ElementImpl
+ */
+ public boolean hasAttributes() {
+ return false; // overridden in ElementImpl
+ }
+
+ /**
+ * Test whether this node has any children. Convenience shorthand
+ * for (Node.getFirstChild()!=null)
+ *
+ * By default we do not have any children, ParentNode overrides this.
+ * @see ParentNode
+ */
+ public boolean hasChildNodes() {
+ return false;
+ }
+
+ /**
+ * Obtain a NodeList enumerating all children of this node. If there
+ * are none, an (initially) empty NodeList is returned.
+ *
+ * NodeLists are "live"; as children are added/removed the NodeList
+ * will immediately reflect those changes. Also, the NodeList refers
+ * to the actual nodes, so changes to those nodes made via the DOM tree
+ * will be reflected in the NodeList and vice versa.
+ *
+ * In this implementation, Nodes implement the NodeList interface and
+ * provide their own getChildNodes() support. Other DOMs may solve this
+ * differently.
+ */
+ public NodeList getChildNodes() {
+ return this;
+ }
+
+ /** The first child of this Node, or null if none.
+ *
+ * By default we do not have any children, ParentNode overrides this.
+ * @see ParentNode
+ */
+ public Node getFirstChild() {
+ return null;
+ }
+
+ /** The first child of this Node, or null if none.
+ *
+ * By default we do not have any children, ParentNode overrides this.
+ * @see ParentNode
+ */
+ public Node getLastChild() {
+ return null;
+ }
+
+ /**
+ * Move one or more node(s) to our list of children. Note that this
+ * implicitly removes them from their previous parent.
+ *
+ * By default we do not accept any children, ParentNode overrides this.
+ * @see ParentNode
+ *
+ * @param newChild The Node to be moved to our subtree. As a
+ * convenience feature, inserting a DocumentNode will instead insert
+ * all its children.
+ *
+ * @param refChild Current child which newChild should be placed
+ * immediately before. If refChild is null, the insertion occurs
+ * after all existing Nodes, like appendChild().
+ *
+ * @return newChild, in its new state (relocated, or emptied in the case of
+ * DocumentNode.)
+ *
+ * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
+ * type that shouldn't be a child of this node, or if newChild is an
+ * ancestor of this node.
+ *
+ * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
+ * different owner document than we do.
+ *
+ * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
+ * this node.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
+ * read-only.
+ */
+ public Node insertBefore(Node newChild, Node refChild)
+ throws DOMException {
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
+ "HIERARCHY_REQUEST_ERR", null));
+ }
+
+ /**
+ * Remove a child from this Node. The removed child's subtree
+ * remains intact so it may be re-inserted elsewhere.
+ *
+ * By default we do not have any children, ParentNode overrides this.
+ * @see ParentNode
+ *
+ * @return oldChild, in its new state (removed).
+ *
+ * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
+ * this node.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
+ * read-only.
+ */
+ public Node removeChild(Node oldChild)
+ throws DOMException {
+ throw new DOMException(DOMException.NOT_FOUND_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
+ "NOT_FOUND_ERR", null));
+ }
+
+ /**
+ * Make newChild occupy the location that oldChild used to
+ * have. Note that newChild will first be removed from its previous
+ * parent, if any. Equivalent to inserting newChild before oldChild,
+ * then removing oldChild.
+ *
+ * By default we do not have any children, ParentNode overrides this.
+ * @see ParentNode
+ *
+ * @return oldChild, in its new state (removed).
+ *
+ * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
+ * type that shouldn't be a child of this node, or if newChild is
+ * one of our ancestors.
+ *
+ * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
+ * different owner document than we do.
+ *
+ * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
+ * this node.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
+ * read-only.
+ */
+ public Node replaceChild(Node newChild, Node oldChild)
+ throws DOMException {
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
+ "HIERARCHY_REQUEST_ERR", null));
+ }
+
+ //
+ // NodeList methods
+ //
+
+ /**
+ * NodeList method: Count the immediate children of this node
+ *
+ * By default we do not have any children, ParentNode overrides this.
+ * @see ParentNode
+ *
+ * @return int
+ */
+ public int getLength() {
+ return 0;
+ }
+
+ /**
+ * NodeList method: Return the Nth immediate child of this node, or
+ * null if the index is out of bounds.
+ *
+ * By default we do not have any children, ParentNode overrides this.
+ * @see ParentNode
+ *
+ * @return org.w3c.dom.Node
+ * @param index int
+ */
+ public Node item(int index) {
+ return null;
+ }
+
+ //
+ // DOM2: methods, getters, setters
+ //
+
+ /**
+ * Puts all Text nodes in the full depth of the sub-tree
+ * underneath this Node , including attribute nodes, into a
+ * "normal" form where only markup (e.g., tags, comments, processing
+ * instructions, CDATA sections, and entity references) separates
+ * Text nodes, i.e., there are no adjacent Text
+ * nodes. This can be used to ensure that the DOM view of a document is
+ * the same as if it were saved and re-loaded, and is useful when
+ * operations (such as XPointer lookups) that depend on a particular
+ * document tree structure are to be used.In cases where the document
+ * contains CDATASections , the normalize operation alone may
+ * not be sufficient, since XPointers do not differentiate between
+ * Text nodes and CDATASection nodes.
+ *
+ * Note that this implementation simply calls normalize() on this Node's
+ * children. It is up to implementors or Node to override normalize()
+ * to take action.
+ */
+ public void normalize() {
+ /* by default we do not have any children,
+ ParentNode overrides this behavior */
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ * Tests whether the DOM implementation implements a specific feature and
+ * that feature is supported by this node.
+ * @param feature The package name of the feature to test. This is the same
+ * name as what can be passed to the method hasFeature on
+ * DOMImplementation.
+ * @param version This is the version number of the package name to
+ * test. In Level 2, version 1, this is the string "2.0". If the version is
+ * not specified, supporting any version of the feature will cause the
+ * method to return true.
+ * @return boolean Returns true if this node defines a subtree within which
+ * the specified feature is supported, false otherwise.
+ * @since WD-DOM-Level-2-19990923
+ */
+ public boolean isSupported(String feature, String version)
+ {
+ return ownerDocument().getImplementation().hasFeature(feature,
+ version);
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * The namespace URI of this node, or null if it is unspecified. When this
+ * node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE, this is
+ * always null and setting it has no effect.
+ *
+ * This is not a computed value that is the result of a namespace lookup
+ * based on an examination of the namespace declarations in scope. It is
+ * merely the namespace URI given at creation time.
+ *
+ * For nodes created with a DOM Level 1 method, such as createElement
+ * from the Document interface, this is null.
+ * @since WD-DOM-Level-2-19990923
+ * @see AttrNSImpl
+ * @see ElementNSImpl
+ */
+ public String getNamespaceURI()
+ {
+ return null;
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * The namespace prefix of this node, or null if it is unspecified. When
+ * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE this
+ * is always null and setting it has no effect.
+ *
+ * For nodes created with a DOM Level 1 method, such as createElement
+ * from the Document interface, this is null.
+ *
+ * @since WD-DOM-Level-2-19990923
+ * @see AttrNSImpl
+ * @see ElementNSImpl
+ */
+ public String getPrefix()
+ {
+ return null;
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * The namespace prefix of this node, or null if it is unspecified. When
+ * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE
+ * this is always null and setting it has no effect.
+ *
+ * For nodes created with a DOM Level 1 method, such as createElement from
+ * the Document interface, this is null.
+ *
+ * Note that setting this attribute changes the nodeName attribute, which
+ * holds the qualified name, as well as the tagName and name attributes of
+ * the Element and Attr interfaces, when applicable.
+ *
+ * @throws INVALID_CHARACTER_ERR Raised if the specified
+ * prefix contains an invalid character.
+ *
+ * @since WD-DOM-Level-2-19990923
+ * @see AttrNSImpl
+ * @see ElementNSImpl
+ */
+ public void setPrefix(String prefix)
+ throws DOMException
+ {
+ throw new DOMException(DOMException.NAMESPACE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
+ "NAMESPACE_ERR", null));
+ }
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * Returns the local part of the qualified name of this node.
+ * For nodes created with a DOM Level 1 method, such as createElement
+ * from the Document interface, and for nodes of any type other than
+ * ELEMENT_NODE and ATTRIBUTE_NODE this is the same as the nodeName
+ * attribute.
+ * @since WD-DOM-Level-2-19990923
+ * @see AttrNSImpl
+ * @see ElementNSImpl
+ */
+ public String getLocalName()
+ {
+ return null;
+ }
+
+ //
+ // EventTarget support
+ //
+
+ public void addEventListener(String type, EventListener listener,
+ boolean useCapture) {
+ // simply forward to Document
+ ownerDocument().addEventListener(this, type, listener, useCapture);
+ }
+
+ public void removeEventListener(String type, EventListener listener,
+ boolean useCapture) {
+ // simply forward to Document
+ ownerDocument().removeEventListener(this, type, listener, useCapture);
+ }
+
+ public boolean dispatchEvent(Event event) {
+ // simply forward to Document
+ return ownerDocument().dispatchEvent(this, event);
+ }
+
+ //
+ // Public DOM Level 3 methods
+ //
+
+ /**
+ * The absolute base URI of this node or null if undefined.
+ * This value is computed according to . However, when the
+ * Document supports the feature "HTML" , the base URI is
+ * computed using first the value of the href attribute of the HTML BASE
+ * element if any, and the value of the documentURI
+ * attribute from the Document interface otherwise.
+ * When the node is an Element , a Document
+ * or a a ProcessingInstruction , this attribute represents
+ * the properties [base URI] defined in . When the node is a
+ * Notation , an Entity , or an
+ * EntityReference , this attribute represents the
+ * properties [declaration base URI] in the . How will this be affected
+ * by resolution of relative namespace URIs issue?It's not.Should this
+ * only be on Document, Element, ProcessingInstruction, Entity, and
+ * Notation nodes, according to the infoset? If not, what is it equal to
+ * on other nodes? Null? An empty string? I think it should be the
+ * parent's.No.Should this be read-only and computed or and actual
+ * read-write attribute?Read-only and computed (F2F 19 Jun 2000 and
+ * teleconference 30 May 2001).If the base HTML element is not yet
+ * attached to a document, does the insert change the Document.baseURI?
+ * Yes. (F2F 26 Sep 2001)
+ * @since DOM Level 3
+ */
+ public String getBaseURI() {
+ return null;
+ }
+
+ /**
+ * Compares a node with this node with regard to their position in the
+ * tree and according to the document order. This order can be extended
+ * by module that define additional types of nodes.
+ * @param other The node to compare against this node.
+ * @return Returns how the given node is positioned relatively to this
+ * node.
+ * @since DOM Level 3
+ * @deprecated
+ */
+ public short compareTreePosition(Node other) {
+ // Questions of clarification for this method - to be answered by the
+ // DOM WG. Current assumptions listed - LM
+ //
+ // 1. How do ENTITY nodes compare?
+ // Current assumption: TREE_POSITION_DISCONNECTED, as ENTITY nodes
+ // aren't really 'in the tree'
+ //
+ // 2. How do NOTATION nodes compare?
+ // Current assumption: TREE_POSITION_DISCONNECTED, as NOTATION nodes
+ // aren't really 'in the tree'
+ //
+ // 3. Are TREE_POSITION_ANCESTOR and TREE_POSITION_DESCENDANT
+ // only relevant for nodes that are "part of the document tree"?
+ //
+ //
+ //
+ // Is the element node "outer" considered an ancestor of "myattr"?
+ // Current assumption: No.
+ //
+ // 4. How do children of ATTRIBUTE nodes compare (with eachother, or
+ // with children of other attribute nodes with the same element)
+ // Current assumption: Children of ATTRIBUTE nodes are treated as if
+ // they they are the attribute node itself, unless the 2 nodes
+ // are both children of the same attribute.
+ //
+ // 5. How does an ENTITY_REFERENCE node compare with it's children?
+ // Given the DOM, it should precede its children as an ancestor.
+ // Given "document order", does it represent the same position?
+ // Current assumption: An ENTITY_REFERENCE node is an ancestor of its
+ // children.
+ //
+ // 6. How do children of a DocumentFragment compare?
+ // Current assumption: If both nodes are part of the same document
+ // fragment, there are compared as if they were part of a document.
+
+
+ // If the nodes are the same...
+ if (this==other)
+ return (TREE_POSITION_SAME_NODE | TREE_POSITION_EQUIVALENT);
+
+ // If either node is of type ENTITY or NOTATION, compare as disconnected
+ short thisType = this.getNodeType();
+ short otherType = other.getNodeType();
+
+ // If either node is of type ENTITY or NOTATION, compare as disconnected
+ if (thisType == Node.ENTITY_NODE ||
+ thisType == Node.NOTATION_NODE ||
+ otherType == Node.ENTITY_NODE ||
+ otherType == Node.NOTATION_NODE ) {
+ return TREE_POSITION_DISCONNECTED;
+ }
+
+ // Find the ancestor of each node, and the distance each node is from
+ // its ancestor.
+ // During this traversal, look for ancestor/descendent relationships
+ // between the 2 nodes in question.
+ // We do this now, so that we get this info correct for attribute nodes
+ // and their children.
+
+ Node node;
+ Node thisAncestor = this;
+ Node otherAncestor = other;
+ int thisDepth=0;
+ int otherDepth=0;
+ for (node=this; node != null; node = node.getParentNode()) {
+ thisDepth +=1;
+ if (node == other)
+ // The other node is an ancestor of this one.
+ return (TREE_POSITION_ANCESTOR | TREE_POSITION_PRECEDING);
+ thisAncestor = node;
+ }
+
+ for (node=other; node!=null; node=node.getParentNode()) {
+ otherDepth +=1;
+ if (node == this)
+ // The other node is a descendent of the reference node.
+ return (TREE_POSITION_DESCENDANT | TREE_POSITION_FOLLOWING);
+ otherAncestor = node;
+ }
+
+
+ Node thisNode = this;
+ Node otherNode = other;
+
+ int thisAncestorType = thisAncestor.getNodeType();
+ int otherAncestorType = otherAncestor.getNodeType();
+
+ // if the ancestor is an attribute, get owning element.
+ // we are now interested in the owner to determine position.
+
+ if (thisAncestorType == Node.ATTRIBUTE_NODE) {
+ thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
+ }
+ if (otherAncestorType == Node.ATTRIBUTE_NODE) {
+ otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
+ }
+
+ // Before proceeding, we should check if both ancestor nodes turned
+ // out to be attributes for the same element
+ if (thisAncestorType == Node.ATTRIBUTE_NODE &&
+ otherAncestorType == Node.ATTRIBUTE_NODE &&
+ thisNode==otherNode)
+ return TREE_POSITION_EQUIVALENT;
+
+ // Now, find the ancestor of the owning element, if the original
+ // ancestor was an attribute
+
+ // Note: the following 2 loops are quite close to the ones above.
+ // May want to common them up. LM.
+ if (thisAncestorType == Node.ATTRIBUTE_NODE) {
+ thisDepth=0;
+ for (node=thisNode; node != null; node=node.getParentNode()) {
+ thisDepth +=1;
+ if (node == otherNode)
+ // The other node is an ancestor of the owning element
+ {
+ return TREE_POSITION_PRECEDING;
+ }
+ thisAncestor = node;
+ }
+ }
+
+ // Now, find the ancestor of the owning element, if the original
+ // ancestor was an attribute
+ if (otherAncestorType == Node.ATTRIBUTE_NODE) {
+ otherDepth=0;
+ for (node=otherNode; node != null; node=node.getParentNode()) {
+ otherDepth +=1;
+ if (node == thisNode)
+ // The other node is a descendent of the reference
+ // node's element
+ return TREE_POSITION_FOLLOWING;
+ otherAncestor = node;
+ }
+ }
+
+ // thisAncestor and otherAncestor must be the same at this point,
+ // otherwise, we are not in the same tree or document fragment
+ if (thisAncestor != otherAncestor)
+ return TREE_POSITION_DISCONNECTED;
+
+
+ // Go up the parent chain of the deeper node, until we find a node
+ // with the same depth as the shallower node
+
+ if (thisDepth > otherDepth) {
+ for (int i=0; i thisDocNum)
+ return DOCUMENT_POSITION_DISCONNECTED |
+ DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
+ else
+ return DOCUMENT_POSITION_DISCONNECTED |
+ DOCUMENT_POSITION_PRECEDING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
+
+ }
+
+ // Find the ancestor of each node, and the distance each node is from
+ // its ancestor.
+ // During this traversal, look for ancestor/descendent relationships
+ // between the 2 nodes in question.
+ // We do this now, so that we get this info correct for attribute nodes
+ // and their children.
+
+ Node node;
+ Node thisAncestor = this;
+ Node otherAncestor = other;
+
+ int thisDepth=0;
+ int otherDepth=0;
+ for (node=this; node != null; node = node.getParentNode()) {
+ thisDepth +=1;
+ if (node == other)
+ // The other node is an ancestor of this one.
+ return (DOCUMENT_POSITION_CONTAINS |
+ DOCUMENT_POSITION_PRECEDING);
+ thisAncestor = node;
+ }
+
+ for (node=other; node!=null; node=node.getParentNode()) {
+ otherDepth +=1;
+ if (node == this)
+ // The other node is a descendent of the reference node.
+ return (DOCUMENT_POSITION_IS_CONTAINED |
+ DOCUMENT_POSITION_FOLLOWING);
+ otherAncestor = node;
+ }
+
+
+
+ int thisAncestorType = thisAncestor.getNodeType();
+ int otherAncestorType = otherAncestor.getNodeType();
+ Node thisNode = this;
+ Node otherNode = other;
+
+ // Special casing for ENTITY, NOTATION, DOCTYPE and ATTRIBUTES
+ // LM: should rewrite this.
+ switch (thisAncestorType) {
+ case Node.NOTATION_NODE:
+ case Node.ENTITY_NODE: {
+ DocumentType container = thisOwnerDoc.getDoctype();
+ if (container == otherAncestor) return
+ (DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING);
+ switch (otherAncestorType) {
+ case Node.NOTATION_NODE:
+ case Node.ENTITY_NODE: {
+ if (thisAncestorType != otherAncestorType)
+ // the nodes are of different types
+ return ((thisAncestorType>otherAncestorType) ?
+ DOCUMENT_POSITION_PRECEDING:DOCUMENT_POSITION_FOLLOWING);
+ else {
+ // the nodes are of the same type. Find order.
+ if (thisAncestorType == Node.NOTATION_NODE)
+
+ if (((NamedNodeMapImpl)container.getNotations()).precedes(otherAncestor,thisAncestor))
+ return (DOCUMENT_POSITION_PRECEDING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+ else
+ return (DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+ else
+ if (((NamedNodeMapImpl)container.getEntities()).precedes(otherAncestor,thisAncestor))
+ return (DOCUMENT_POSITION_PRECEDING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+ else
+ return (DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+ }
+ }
+ }
+ thisNode = thisAncestor = thisOwnerDoc;
+ break;
+ }
+ case Node.DOCUMENT_TYPE_NODE: {
+ if (otherNode == thisOwnerDoc)
+ return (DOCUMENT_POSITION_PRECEDING |
+ DOCUMENT_POSITION_CONTAINS);
+ else if (thisOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
+ return (DOCUMENT_POSITION_FOLLOWING);
+ break;
+ }
+ case Node.ATTRIBUTE_NODE: {
+ thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
+ if (otherAncestorType==Node.ATTRIBUTE_NODE) {
+ otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
+ if (otherNode == thisNode) {
+ if (((NamedNodeMapImpl)thisNode.getAttributes()).precedes(other,this))
+ return (DOCUMENT_POSITION_PRECEDING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+ else
+ return (DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+ }
+ }
+
+ // Now, find the ancestor of the element
+ thisDepth=0;
+ for (node=thisNode; node != null; node=node.getParentNode()) {
+ thisDepth +=1;
+ if (node == otherNode)
+ {
+ // The other node is an ancestor of the owning element
+ return (DOCUMENT_POSITION_CONTAINS |
+ DOCUMENT_POSITION_PRECEDING);
+ }
+ thisAncestor = node;
+ }
+ }
+ }
+ switch (otherAncestorType) {
+ case Node.NOTATION_NODE:
+ case Node.ENTITY_NODE: {
+ DocumentType container = thisOwnerDoc.getDoctype();
+ if (container == this) return (DOCUMENT_POSITION_IS_CONTAINED |
+ DOCUMENT_POSITION_FOLLOWING);
+ otherNode = otherAncestor = thisOwnerDoc;
+ break;
+ }
+ case Node.DOCUMENT_TYPE_NODE: {
+ if (thisNode == otherOwnerDoc)
+ return (DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_IS_CONTAINED);
+ else if (otherOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
+ return (DOCUMENT_POSITION_PRECEDING);
+ break;
+ }
+ case Node.ATTRIBUTE_NODE: {
+ otherDepth=0;
+ otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
+ for (node=otherNode; node != null; node=node.getParentNode()) {
+ otherDepth +=1;
+ if (node == thisNode)
+ // The other node is a descendent of the reference
+ // node's element
+ return DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_IS_CONTAINED;
+ otherAncestor = node;
+ }
+
+ }
+ }
+
+ // thisAncestor and otherAncestor must be the same at this point,
+ // otherwise, the original nodes are disconnected
+ if (thisAncestor != otherAncestor) {
+ int thisAncestorNum, otherAncestorNum;
+ thisAncestorNum = ((NodeImpl)thisAncestor).getNodeNumber();
+ otherAncestorNum = ((NodeImpl)otherAncestor).getNodeNumber();
+
+ if (thisAncestorNum > otherAncestorNum)
+ return DOCUMENT_POSITION_DISCONNECTED |
+ DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
+ else
+ return DOCUMENT_POSITION_DISCONNECTED |
+ DOCUMENT_POSITION_PRECEDING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
+ }
+
+
+ // Go up the parent chain of the deeper node, until we find a node
+ // with the same depth as the shallower node
+
+ if (thisDepth > otherDepth) {
+ for (int i=0; iText node containing the string
+ * this attribute is set to. On getting, no serialization is performed,
+ * the returned string does not contain any markup. No whitespace
+ * normalization is performed, the returned string does not contain the
+ * element content whitespaces . Similarly, on setting, no parsing is
+ * performed either, the input string is taken as pure textual content.
+ * The string returned is made of the text content of this node
+ * depending on its type, as defined below:
+ *
+ *
+ * Node type |
+ * Content |
+ *
+
+ /**
+ * This attribute returns the text content of this node and its
+ * descendants. When it is defined to be null, setting it has no effect.
+ * When set, any possible children this node may have are removed and
+ * replaced by a single Text node containing the string
+ * this attribute is set to. On getting, no serialization is performed,
+ * the returned string does not contain any markup. No whitespace
+ * normalization is performed, the returned string does not contain the
+ * element content whitespaces . Similarly, on setting, no parsing is
+ * performed either, the input string is taken as pure textual content.
+ * The string returned is made of the text content of this node
+ * depending on its type, as defined below:
+ *
+ *
+ * Node type |
+ * Content |
+ *
+ *
+ *
+ * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
+ * DOCUMENT_FRAGMENT_NODE |
+ * concatenation of the textContent
+ * attribute value of every child node, excluding COMMENT_NODE and
+ * PROCESSING_INSTRUCTION_NODE nodes |
+ *
+ *
+ * ATTRIBUTE_NODE, TEXT_NODE,
+ * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE |
+ *
+ * nodeValue |
+ *
+ *
+ * DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE |
+ *
+ * null |
+ *
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
+ * @exception DOMException
+ * DOMSTRING_SIZE_ERR: Raised when it would return more characters than
+ * fit in a DOMString variable on the implementation
+ * platform.
+ * @since DOM Level 3
+ */
+ public String getTextContent() throws DOMException {
+ return getNodeValue(); // overriden in some subclasses
+ }
+
+ // internal method taking a StringBuffer in parameter
+ void getTextContent(StringBuffer buf) throws DOMException {
+ String content = getNodeValue();
+ if (content != null) {
+ buf.append(content);
+ }
+ }
+
+ /**
+ * This attribute returns the text content of this node and its
+ * descendants. When it is defined to be null, setting it has no effect.
+ * When set, any possible children this node may have are removed and
+ * replaced by a single Text node containing the string
+ * this attribute is set to. On getting, no serialization is performed,
+ * the returned string does not contain any markup. No whitespace
+ * normalization is performed, the returned string does not contain the
+ * element content whitespaces . Similarly, on setting, no parsing is
+ * performed either, the input string is taken as pure textual content.
+ * The string returned is made of the text content of this node
+ * depending on its type, as defined below:
+ *
+ *
+ * Node type |
+ * Content |
+ *
+ *
+ *
+ * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
+ * DOCUMENT_FRAGMENT_NODE |
+ * concatenation of the textContent
+ * attribute value of every child node, excluding COMMENT_NODE and
+ * PROCESSING_INSTRUCTION_NODE nodes |
+ *
+ *
+ * ATTRIBUTE_NODE, TEXT_NODE,
+ * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE |
+ *
+ * nodeValue |
+ *
+ *
+ * DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE |
+ *
+ * null |
+ *
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
+ * @exception DOMException
+ * DOMSTRING_SIZE_ERR: Raised when it would return more characters than
+ * fit in a DOMString variable on the implementation
+ * platform.
+ * @since DOM Level 3
+ */
+ public void setTextContent(String textContent)
+ throws DOMException {
+ setNodeValue(textContent);
+ }
+
+ /**
+ * Returns whether this node is the same node as the given one.
+ * This method provides a way to determine whether two
+ * Node references returned by the implementation reference
+ * the same object. When two Node references are references
+ * to the same object, even if through a proxy, the references may be
+ * used completely interchangably, such that all attributes have the
+ * same values and calling the same DOM method on either reference
+ * always has exactly the same effect.
+ * @param other The node to test against.
+ * @return Returns true if the nodes are the same,
+ * false otherwise.
+ * @since DOM Level 3
+ */
+ public boolean isSameNode(Node other) {
+ // we do not use any wrapper so the answer is obvious
+ return this == other;
+ }
+
+
+
+
+ /**
+ * DOM Level 3: Experimental
+ * This method checks if the specified namespaceURI is the
+ * default namespace or not.
+ * @param namespaceURI The namespace URI to look for.
+ * @return true if the specified namespaceURI
+ * is the default namespace, false otherwise.
+ * @since DOM Level 3
+ */
+ public boolean isDefaultNamespace(String namespaceURI){
+ // REVISIT: remove casts when DOM L3 becomes REC.
+ short type = this.getNodeType();
+ switch (type) {
+ case Node.ELEMENT_NODE: {
+ String namespace = this.getNamespaceURI();
+ String prefix = this.getPrefix();
+
+ // REVISIT: is it possible that prefix is empty string?
+ if (prefix == null || prefix.length() == 0) {
+ if (namespaceURI == null) {
+ return (namespace == namespaceURI);
+ }
+ return namespaceURI.equals(namespace);
+ }
+ if (this.hasAttributes()) {
+ ElementImpl elem = (ElementImpl)this;
+ NodeImpl attr = (NodeImpl)elem.getAttributeNodeNS("http://www.w3.org/2000/xmlns/", "xmlns");
+ if (attr != null) {
+ String value = attr.getNodeValue();
+ if (namespaceURI == null) {
+ return (namespace == value);
+ }
+ return namespaceURI.equals(value);
+ }
+ }
+
+ NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
+ if (ancestor != null) {
+ return ancestor.isDefaultNamespace(namespaceURI);
+ }
+ return false;
+ }
+ case Node.DOCUMENT_NODE:{
+ Element docElement = ((Document)this).getDocumentElement();
+ if (docElement != null) {
+ return docElement.isDefaultNamespace(namespaceURI);
+ }
+ return false;
+ }
+
+ case Node.ENTITY_NODE :
+ case Node.NOTATION_NODE:
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ case Node.DOCUMENT_TYPE_NODE:
+ // type is unknown
+ return false;
+ case Node.ATTRIBUTE_NODE:{
+ if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
+ return ownerNode.isDefaultNamespace(namespaceURI);
+
+ }
+ return false;
+ }
+ default:{
+ NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
+ if (ancestor != null) {
+ return ancestor.isDefaultNamespace(namespaceURI);
+ }
+ return false;
+ }
+
+ }
+
+
+ }
+
+
+ /**
+ *
+ * DOM Level 3 - Experimental:
+ * Look up the prefix associated to the given namespace URI, starting from this node.
+ *
+ * @param namespaceURI
+ * @return the prefix for the namespace
+ */
+ public String lookupPrefix(String namespaceURI){
+
+ // REVISIT: When Namespaces 1.1 comes out this may not be true
+ // Prefix can't be bound to null namespace
+ if (namespaceURI == null) {
+ return null;
+ }
+
+ short type = this.getNodeType();
+
+ switch (type) {
+ case Node.ELEMENT_NODE: {
+ this.getNamespaceURI(); // to flip out children
+ return lookupNamespacePrefix(namespaceURI, (ElementImpl)this);
+ }
+ case Node.DOCUMENT_NODE:{
+ Element docElement = ((Document)this).getDocumentElement();
+ if (docElement != null) {
+ return docElement.lookupPrefix(namespaceURI);
+ }
+ return null;
+ }
+
+ case Node.ENTITY_NODE :
+ case Node.NOTATION_NODE:
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ case Node.DOCUMENT_TYPE_NODE:
+ // type is unknown
+ return null;
+ case Node.ATTRIBUTE_NODE:{
+ if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
+ return ownerNode.lookupPrefix(namespaceURI);
+
+ }
+ return null;
+ }
+ default:{
+ NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
+ if (ancestor != null) {
+ return ancestor.lookupPrefix(namespaceURI);
+ }
+ return null;
+ }
+
+ }
+ }
+ /**
+ * DOM Level 3 - Experimental:
+ * Look up the namespace URI associated to the given prefix, starting from this node.
+ * Use lookupNamespaceURI(null) to lookup the default namespace
+ *
+ * @param specifiedPrefix
+ * @return the URI for the namespace
+ * @since DOM Level 3
+ */
+ public String lookupNamespaceURI(String specifiedPrefix) {
+ short type = this.getNodeType();
+ switch (type) {
+ case Node.ELEMENT_NODE : {
+
+ String namespace = this.getNamespaceURI();
+ String prefix = this.getPrefix();
+ if (namespace !=null) {
+ // REVISIT: is it possible that prefix is empty string?
+ if (specifiedPrefix== null && prefix==specifiedPrefix) {
+ // looking for default namespace
+ return namespace;
+ } else if (prefix != null && prefix.equals(specifiedPrefix)) {
+ // non default namespace
+ return namespace;
+ }
+ }
+ if (this.hasAttributes()) {
+ NamedNodeMap map = this.getAttributes();
+ int length = map.getLength();
+ for (int i=0;i 0 ? value : null;
+ } else if (attrPrefix !=null &&
+ attrPrefix.equals("xmlns") &&
+ attr.getLocalName().equals(specifiedPrefix)) {
+ // non default namespace
+ return value.length() > 0 ? value : null;
+ }
+ }
+ }
+ }
+ NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
+ if (ancestor != null) {
+ return ancestor.lookupNamespaceURI(specifiedPrefix);
+ }
+
+ return null;
+
+
+ }
+ case Node.DOCUMENT_NODE : {
+ Element docElement = ((Document)this).getDocumentElement();
+ if (docElement != null) {
+ return docElement.lookupNamespaceURI(specifiedPrefix);
+ }
+ return null;
+ }
+ case Node.ENTITY_NODE :
+ case Node.NOTATION_NODE:
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ case Node.DOCUMENT_TYPE_NODE:
+ // type is unknown
+ return null;
+ case Node.ATTRIBUTE_NODE:{
+ if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
+ return ownerNode.lookupNamespaceURI(specifiedPrefix);
+
+ }
+ return null;
+ }
+ default:{
+ NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
+ if (ancestor != null) {
+ return ancestor.lookupNamespaceURI(specifiedPrefix);
+ }
+ return null;
+ }
+
+ }
+ }
+
+ Node getElementAncestor(Node currentNode) {
+ Node parent = currentNode.getParentNode();
+ while (parent != null) {
+ short type = parent.getNodeType();
+ if (type == Node.ELEMENT_NODE) {
+ return parent;
+ }
+ parent = parent.getParentNode();
+ }
+ return null;
+ }
+
+ String lookupNamespacePrefix(String namespaceURI, ElementImpl el){
+ String namespace = this.getNamespaceURI();
+ // REVISIT: if no prefix is available is it null or empty string, or
+ // could be both?
+ String prefix = this.getPrefix();
+
+ if (namespace!=null && namespace.equals(namespaceURI)) {
+ if (prefix != null) {
+ String foundNamespace = el.lookupNamespaceURI(prefix);
+ if (foundNamespace !=null && foundNamespace.equals(namespaceURI)) {
+ return prefix;
+ }
+
+ }
+ }
+ if (this.hasAttributes()) {
+ NamedNodeMap map = this.getAttributes();
+ int length = map.getLength();
+ for (int i=0;iThis method tests for equality of nodes, not sameness (i.e.,
+ * whether the two nodes are references to the same object) which can be
+ * tested with Node.isSameNode . All nodes that are the same
+ * will also be equal, though the reverse may not be true.
+ * Two nodes are equal if and only if the following conditions are
+ * satisfied: The two nodes are of the same type.The following string
+ * attributes are equal: nodeName , localName ,
+ * namespaceURI , prefix , nodeValue
+ * , baseURI . This is: they are both null , or
+ * they have the same length and are character for character identical.
+ * The attributes NamedNodeMaps are equal.
+ * This is: they are both null , or they have the same
+ * length and for each node that exists in one map there is a node that
+ * exists in the other map and is equal, although not necessarily at the
+ * same index.The childNodes NodeLists are
+ * equal. This is: they are both null , or they have the
+ * same length and contain equal nodes at the same index. This is true
+ * for Attr nodes as for any other type of node. Note that
+ * normalization can affect equality; to avoid this, nodes should be
+ * normalized before being compared.
+ * For two DocumentType nodes to be equal, the following
+ * conditions must also be satisfied: The following string attributes
+ * are equal: publicId , systemId ,
+ * internalSubset .The entities
+ * NamedNodeMaps are equal.The notations
+ * NamedNodeMaps are equal.
+ * On the other hand, the following do not affect equality: the
+ * ownerDocument attribute, the specified
+ * attribute for Attr nodes, the
+ * isWhitespaceInElementContent attribute for
+ * Text nodes, as well as any user data or event listeners
+ * registered on the nodes.
+ * @param arg The node to compare equality with.
+ * @return If the nodes, and possibly subtrees are equal,
+ * true otherwise false .
+ * @since DOM Level 3
+ */
+ public boolean isEqualNode(Node arg) {
+ if (arg == this) {
+ return true;
+ }
+ if (arg.getNodeType() != getNodeType()) {
+ return false;
+ }
+ // in theory nodeName can't be null but better be careful
+ // who knows what other implementations may be doing?...
+ if (getNodeName() == null) {
+ if (arg.getNodeName() != null) {
+ return false;
+ }
+ }
+ else if (!getNodeName().equals(arg.getNodeName())) {
+ return false;
+ }
+
+ if (getLocalName() == null) {
+ if (arg.getLocalName() != null) {
+ return false;
+ }
+ }
+ else if (!getLocalName().equals(arg.getLocalName())) {
+ return false;
+ }
+
+ if (getNamespaceURI() == null) {
+ if (arg.getNamespaceURI() != null) {
+ return false;
+ }
+ }
+ else if (!getNamespaceURI().equals(arg.getNamespaceURI())) {
+ return false;
+ }
+
+ if (getPrefix() == null) {
+ if (arg.getPrefix() != null) {
+ return false;
+ }
+ }
+ else if (!getPrefix().equals(arg.getPrefix())) {
+ return false;
+ }
+
+ if (getNodeValue() == null) {
+ if (arg.getNodeValue() != null) {
+ return false;
+ }
+ }
+ else if (!getNodeValue().equals(arg.getNodeValue())) {
+ return false;
+ }
+
+
+ return true;
+ }
+
+ /**
+ * @since DOM Level 3
+ */
+ public Object getFeature(String feature, String version) {
+ // we don't have any alternate node, either this node does the job
+ // or we don't have anything that does
+ return isSupported(feature, version) ? this : null;
+ }
+
+ /**
+ * Associate an object to a key on this node. The object can later be
+ * retrieved from this node by calling getUserData with the
+ * same key.
+ * @param key The key to associate the object to.
+ * @param data The object to associate to the given key, or
+ * null to remove any existing association to that key.
+ * @param handler The handler to associate to that key, or
+ * null .
+ * @return Returns the DOMObject previously associated to
+ * the given key on this node, or null if there was none.
+ * @since DOM Level 3
+ */
+ public Object setUserData(String key,
+ Object data,
+ UserDataHandler handler) {
+ return ownerDocument().setUserData(this, key, data, handler);
+ }
+
+ /**
+ * Retrieves the object associated to a key on a this node. The object
+ * must first have been set to this node by calling
+ * setUserData with the same key.
+ * @param key The key the object is associated to.
+ * @return Returns the DOMObject associated to the given key
+ * on this node, or null if there was none.
+ * @since DOM Level 3
+ */
+ public Object getUserData(String key) {
+ return ownerDocument().getUserData(this, key);
+ }
+
+ protected Hashtable getUserDataRecord(){
+ return ownerDocument().getUserDataRecord(this);
+ }
+
+ //
+ // Public methods
+ //
+
+ /**
+ * NON-DOM: PR-DOM-Level-1-19980818 mentions readonly nodes in conjunction
+ * with Entities, but provides no API to support this.
+ *
+ * Most DOM users should not touch this method. Its anticpated use
+ * is during construction of EntityRefernces, where it will be used to
+ * lock the contents replicated from Entity so they can't be casually
+ * altered. It _could_ be published as a DOM extension, if desired.
+ *
+ * Note: since we never have any children deep is meaningless here,
+ * ParentNode overrides this behavior.
+ * @see ParentNode
+ *
+ * @param readOnly True or false as desired.
+ * @param deep If true, children are also toggled. Note that this will
+ * not change the state of an EntityReference or its children,
+ * which are always read-only.
+ */
+ public void setReadOnly(boolean readOnly, boolean deep) {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ isReadOnly(readOnly);
+
+ } // setReadOnly(boolean,boolean)
+
+ /**
+ * NON-DOM: Returns true if this node is read-only. This is a
+ * shallow check.
+ */
+ public boolean getReadOnly() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return isReadOnly();
+
+ } // getReadOnly():boolean
+
+ /**
+ * NON-DOM: As an alternative to subclassing the DOM, this implementation
+ * has been extended with the ability to attach an object to each node.
+ * (If you need multiple objects, you can attach a collection such as a
+ * vector or hashtable, then attach your application information to that.)
+ * Important Note: You are responsible for removing references
+ * to your data on nodes that are no longer used. Failure to do so will
+ * prevent the nodes, your data is attached to, to be garbage collected
+ * until the whole document is.
+ *
+ * @param data the object to store or null to remove any existing reference
+ */
+ public void setUserData(Object data) {
+ ownerDocument().setUserData(this, data);
+ }
+
+ /**
+ * NON-DOM:
+ * Returns the user data associated to this node.
+ */
+ public Object getUserData() {
+ return ownerDocument().getUserData(this);
+ }
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * Denotes that this node has changed.
+ */
+ protected void changed() {
+ // we do not actually store this information on every node, we only
+ // have a global indicator on the Document. Doing otherwise cost us too
+ // much for little gain.
+ ownerDocument().changed();
+ }
+
+ /**
+ * Returns the number of changes to this node.
+ */
+ protected int changes() {
+ // we do not actually store this information on every node, we only
+ // have a global indicator on the Document. Doing otherwise cost us too
+ // much for little gain.
+ return ownerDocument().changes();
+ }
+
+ /**
+ * Override this method in subclass to hook in efficient
+ * internal data structure.
+ */
+ protected void synchronizeData() {
+ // By default just change the flag to avoid calling this method again
+ needsSyncData(false);
+ }
+
+ /**
+ * For non-child nodes, the node which "points" to this node.
+ * For example, the owning element for an attribute
+ */
+ protected Node getContainer() {
+ return null;
+ }
+
+
+ /*
+ * Flags setters and getters
+ */
+
+ final boolean isReadOnly() {
+ return (flags & READONLY) != 0;
+ }
+
+ final void isReadOnly(boolean value) {
+ flags = (short) (value ? flags | READONLY : flags & ~READONLY);
+ }
+
+ final boolean needsSyncData() {
+ return (flags & SYNCDATA) != 0;
+ }
+
+ final void needsSyncData(boolean value) {
+ flags = (short) (value ? flags | SYNCDATA : flags & ~SYNCDATA);
+ }
+
+ final boolean needsSyncChildren() {
+ return (flags & SYNCCHILDREN) != 0;
+ }
+
+ public final void needsSyncChildren(boolean value) {
+ flags = (short) (value ? flags | SYNCCHILDREN : flags & ~SYNCCHILDREN);
+ }
+
+ final boolean isOwned() {
+ return (flags & OWNED) != 0;
+ }
+
+ final void isOwned(boolean value) {
+ flags = (short) (value ? flags | OWNED : flags & ~OWNED);
+ }
+
+ final boolean isFirstChild() {
+ return (flags & FIRSTCHILD) != 0;
+ }
+
+ final void isFirstChild(boolean value) {
+ flags = (short) (value ? flags | FIRSTCHILD : flags & ~FIRSTCHILD);
+ }
+
+ final boolean isSpecified() {
+ return (flags & SPECIFIED) != 0;
+ }
+
+ final void isSpecified(boolean value) {
+ flags = (short) (value ? flags | SPECIFIED : flags & ~SPECIFIED);
+ }
+
+ // inconsistent name to avoid clash with public method on TextImpl
+ final boolean internalIsIgnorableWhitespace() {
+ return (flags & IGNORABLEWS) != 0;
+ }
+
+ final void isIgnorableWhitespace(boolean value) {
+ flags = (short) (value ? flags | IGNORABLEWS : flags & ~IGNORABLEWS);
+ }
+
+ final boolean hasStringValue() {
+ return (flags & HASSTRING) != 0;
+ }
+
+ final void hasStringValue(boolean value) {
+ flags = (short) (value ? flags | HASSTRING : flags & ~HASSTRING);
+ }
+
+ final boolean isNormalized() {
+ return (flags & NORMALIZED) != 0;
+ }
+
+ final void isNormalized(boolean value) {
+ // See if flag should propagate to parent.
+ if (!value && isNormalized() && ownerNode != null) {
+ ownerNode.isNormalized(false);
+ }
+ flags = (short) (value ? flags | NORMALIZED : flags & ~NORMALIZED);
+ }
+
+ final boolean isIdAttribute() {
+ return (flags & ID) != 0;
+ }
+
+ final void isIdAttribute(boolean value) {
+ flags = (short) (value ? flags | ID : flags & ~ID);
+ }
+
+ //
+ // Object methods
+ //
+
+ /** NON-DOM method for debugging convenience. */
+ public String toString() {
+ return "["+getNodeName()+": "+getNodeValue()+"]";
+ }
+
+ //
+ // Serialization methods
+ //
+
+ /** Serialize object. */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+
+ // synchronize data
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ // write object
+ out.defaultWriteObject();
+
+ } // writeObject(ObjectOutputStream)
+
+} // class NodeImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/NodeIteratorImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/NodeIteratorImpl.java
new file mode 100644
index 0000000..52a8b94
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/NodeIteratorImpl.java
@@ -0,0 +1,372 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+
+
+/** DefaultNodeIterator implements a NodeIterator, which iterates a
+ * DOM tree in the expected depth first way.
+ *
+ * The whatToShow and filter functionality is implemented as expected.
+ *
+ * This class also has method removeNode to enable iterator "fix-up"
+ * on DOM remove. It is expected that the DOM implementation call removeNode
+ * right before the actual DOM transformation. If not called by the DOM,
+ * the client could call it before doing the removal.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class NodeIteratorImpl implements NodeIterator {
+
+ //
+ // Data
+ //
+
+ /** The DocumentImpl which created this iterator, so it can be detached. */
+ private DocumentImpl fDocument;
+ /** The root. */
+ private Node fRoot;
+ /** The whatToShow mask. */
+ private int fWhatToShow = NodeFilter.SHOW_ALL;
+ /** The NodeFilter reference. */
+ private NodeFilter fNodeFilter;
+ /** If detach is called, the fDetach flag is true, otherwise flase. */
+ private boolean fDetach = false;
+
+ //
+ // Iterator state - current node and direction.
+ //
+ // Note: The current node and direction are sufficient to implement
+ // the desired behaviour of the current pointer being _between_
+ // two nodes. The fCurrentNode is actually the last node returned,
+ // and the
+ // direction is whether the pointer is in front or behind this node.
+ // (usually akin to whether the node was returned via nextNode())
+ // (eg fForward = true) or previousNode() (eg fForward = false).
+ // Note also, if removing a Node, the fCurrentNode
+ // can be placed on a Node which would not pass filters.
+
+ /** The last Node returned. */
+ private Node fCurrentNode;
+
+ /** The direction of the iterator on the fCurrentNode.
+ *
+ * nextNode() == fForward = true;
+ * previousNode() == fForward = false;
+ *
+ */
+ private boolean fForward = true;
+
+ /** When TRUE, the children of entites references are returned in the iterator. */
+ private boolean fEntityReferenceExpansion;
+
+ //
+ // Constructor
+ //
+
+ /** Public constructor */
+ public NodeIteratorImpl( DocumentImpl document,
+ Node root,
+ int whatToShow,
+ NodeFilter nodeFilter,
+ boolean entityReferenceExpansion) {
+ fDocument = document;
+ fRoot = root;
+ fCurrentNode = null;
+ fWhatToShow = whatToShow;
+ fNodeFilter = nodeFilter;
+ fEntityReferenceExpansion = entityReferenceExpansion;
+ }
+
+ public Node getRoot() {
+ return fRoot;
+ }
+
+ // Implementation Note: Note that the iterator looks at whatToShow
+ // and filter values at each call, and therefore one _could_ add
+ // setters for these values and alter them while iterating!
+
+ /** Return the whatToShow value */
+ public int getWhatToShow() {
+ return fWhatToShow;
+ }
+
+ /** Return the filter */
+ public NodeFilter getFilter() {
+ return fNodeFilter;
+ }
+
+ /** Return whether children entity references are included in the iterator. */
+ public boolean getExpandEntityReferences() {
+ return fEntityReferenceExpansion;
+ }
+
+ /** Return the next Node in the Iterator. The node is the next node in
+ * depth-first order which also passes the filter, and whatToShow.
+ * If there is no next node which passes these criteria, then return null.
+ */
+ public Node nextNode() {
+
+ if( fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+
+ // if root is null there is no next node.
+ if (fRoot == null) return null;
+
+ Node nextNode = fCurrentNode;
+ boolean accepted = false; // the next node has not been accepted.
+
+ accepted_loop:
+ while (!accepted) {
+
+ // if last direction is not forward, repeat node.
+ if (!fForward && nextNode!=null) {
+ //System.out.println("nextNode():!fForward:"+fCurrentNode.getNodeName());
+ nextNode = fCurrentNode;
+ } else {
+ // else get the next node via depth-first
+ if (!fEntityReferenceExpansion
+ && nextNode != null
+ && nextNode.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+ nextNode = nextNode(nextNode, false);
+ } else {
+ nextNode = nextNode(nextNode, true);
+ }
+ }
+
+ fForward = true; //REVIST: should direction be set forward before null check?
+
+ // nothing in the list. return null.
+ if (nextNode == null) return null;
+
+ // does node pass the filters and whatToShow?
+ accepted = acceptNode(nextNode);
+ if (accepted) {
+ // if so, then the node is the current node.
+ fCurrentNode = nextNode;
+ return fCurrentNode;
+ } else
+ continue accepted_loop;
+
+ } // while (!accepted) {
+
+ // no nodes, or no accepted nodes.
+ return null;
+
+ }
+
+ /** Return the previous Node in the Iterator. The node is the next node in
+ * _backwards_ depth-first order which also passes the filter, and whatToShow.
+ */
+ public Node previousNode() {
+
+ if( fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+
+ // if the root is null, or the current node is null, return null.
+ if (fRoot == null || fCurrentNode == null) return null;
+
+ Node previousNode = fCurrentNode;
+ boolean accepted = false;
+
+ accepted_loop:
+ while (!accepted) {
+
+ if (fForward && previousNode != null) {
+ //repeat last node.
+ previousNode = fCurrentNode;
+ } else {
+ // get previous node in backwards depth first order.
+ previousNode = previousNode(previousNode);
+ }
+
+ // we are going backwards
+ fForward = false;
+
+ // if the new previous node is null, we're at head or past the root,
+ // so return null.
+ if (previousNode == null) return null;
+
+ // check if node passes filters and whatToShow.
+ accepted = acceptNode(previousNode);
+ if (accepted) {
+ // if accepted, update the current node, and return it.
+ fCurrentNode = previousNode;
+ return fCurrentNode;
+ } else
+ continue accepted_loop;
+ }
+ // there are no nodes?
+ return null;
+ }
+
+ /** The node is accepted if it passes the whatToShow and the filter. */
+ boolean acceptNode(Node node) {
+
+ if (fNodeFilter == null) {
+ return ( fWhatToShow & (1 << node.getNodeType()-1)) != 0 ;
+ } else {
+ return ((fWhatToShow & (1 << node.getNodeType()-1)) != 0 )
+ && fNodeFilter.acceptNode(node) == NodeFilter.FILTER_ACCEPT;
+ }
+ }
+
+ /** Return node, if matches or any parent if matches. */
+ Node matchNodeOrParent(Node node) {
+ // Additions and removals in the underlying data structure may occur
+ // before any iterations, and in this case the reference_node is null.
+ if (fCurrentNode == null) return null;
+
+ // check if the removed node is an _ancestor_ of the
+ // reference node
+ for (Node n = fCurrentNode; n != fRoot; n = n.getParentNode()) {
+ if (node == n) return n;
+ }
+ return null;
+ }
+
+ /** The method nextNode(Node, boolean) returns the next node
+ * from the actual DOM tree.
+ *
+ * The boolean visitChildren determines whether to visit the children.
+ * The result is the nextNode.
+ */
+ Node nextNode(Node node, boolean visitChildren) {
+
+ if (node == null) return fRoot;
+
+ Node result;
+ // only check children if we visit children.
+ if (visitChildren) {
+ //if hasChildren, return 1st child.
+ if (node.hasChildNodes()) {
+ result = node.getFirstChild();
+ return result;
+ }
+ }
+
+ if (node == fRoot) { //if Root has no kids
+ return null;
+ }
+
+ // if hasSibling, return sibling
+ result = node.getNextSibling();
+ if (result != null) return result;
+
+
+ // return parent's 1st sibling.
+ Node parent = node.getParentNode();
+ while (parent != null && parent != fRoot) {
+ result = parent.getNextSibling();
+ if (result != null) {
+ return result;
+ } else {
+ parent = parent.getParentNode();
+ }
+
+ } // while (parent != null && parent != fRoot) {
+
+ // end of list, return null
+ return null;
+ }
+
+ /** The method previousNode(Node) returns the previous node
+ * from the actual DOM tree.
+ */
+ Node previousNode(Node node) {
+
+ Node result;
+
+ // if we're at the root, return null.
+ if (node == fRoot) return null;
+
+ // get sibling
+ result = node.getPreviousSibling();
+ if (result == null) {
+ //if 1st sibling, return parent
+ result = node.getParentNode();
+ return result;
+ }
+
+ // if sibling has children, keep getting last child of child.
+ if (result.hasChildNodes()
+ && !(!fEntityReferenceExpansion
+ && result != null
+ && result.getNodeType() == Node.ENTITY_REFERENCE_NODE))
+
+ {
+ while (result.hasChildNodes()) {
+ result = result.getLastChild();
+ }
+ }
+
+ return result;
+ }
+
+ /** Fix-up the iterator on a remove. Called by DOM or otherwise,
+ * before an actual DOM remove.
+ */
+ public void removeNode(Node node) {
+
+ // Implementation note: Fix-up means setting the current node properly
+ // after a remove.
+
+ if (node == null) return;
+
+ Node deleted = matchNodeOrParent(node);
+
+ if (deleted == null) return;
+
+ if (fForward) {
+ fCurrentNode = previousNode(deleted);
+ } else
+ // if (!fForward)
+ {
+ Node next = nextNode(deleted, false);
+ if (next!=null) {
+ // normal case: there _are_ nodes following this in the iterator.
+ fCurrentNode = next;
+ } else {
+ // the last node in the iterator is to be removed,
+ // so we set the current node to be the previous one.
+ fCurrentNode = previousNode(deleted);
+ fForward = true;
+ }
+
+ }
+
+ }
+
+ public void detach() {
+ fDetach = true;
+ fDocument.removeNodeIterator(this);
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/NodeListCache.java b/resources/xerces2-j-src/org/apache/xerces/dom/NodeListCache.java
new file mode 100644
index 0000000..133b8d5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/NodeListCache.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.Serializable;
+
+/**
+ * This class is used, via a pool managed on CoreDocumentImpl, in ParentNode to
+ * improve performance of the NodeList accessors, getLength() and item(i).
+ *
+ * @xerces.internal
+ *
+ * @author Arnaud Le Hors, IBM
+ *
+ * @version $Id$
+ */
+class NodeListCache implements Serializable {
+
+ /** Serialization version. */
+ private static final long serialVersionUID = -7927529254918631002L;
+
+ /** Cached node list length. */
+ int fLength = -1;
+
+ /** Last requested node index. */
+ int fChildIndex = -1;
+
+ /** Last requested node. */
+ ChildNode fChild;
+
+ /** Owner of this cache */
+ ParentNode fOwner;
+
+ /** Pointer to the next object on the list,
+ only meaningful when actully stored in the free list. */
+ NodeListCache next;
+
+ NodeListCache(ParentNode owner) {
+ fOwner = owner;
+ }
+}
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/NotationImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/NotationImpl.java
new file mode 100644
index 0000000..2e32325
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/NotationImpl.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.apache.xerces.util.URI;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.Notation;
+
+/**
+ * Notations are how the Document Type Description (DTD) records hints
+ * about the format of an XML "unparsed entity" -- in other words,
+ * non-XML data bound to this document type, which some applications
+ * may wish to consult when manipulating the document. A Notation
+ * represents a name-value pair, with its nodeName being set to the
+ * declared name of the notation.
+ *
+ * Notations are also used to formally declare the "targets" of
+ * Processing Instructions.
+ *
+ * Note that the Notation's data is non-DOM information; the DOM only
+ * records what and where it is.
+ *
+ * See the XML 1.0 spec, sections 4.7 and 2.6, for more info.
+ *
+ * Level 1 of the DOM does not support editing Notation contents.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class NotationImpl
+ extends NodeImpl
+ implements Notation {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -764632195890658402L;
+
+ //
+ // Data
+ //
+
+ /** Notation name. */
+ protected String name;
+
+ /** Public identifier. */
+ protected String publicId;
+
+ /** System identifier. */
+ protected String systemId;
+
+ /** Base URI*/
+ protected String baseURI;
+
+ //
+ // Constructors
+ //
+
+ /** Factory constructor. */
+ public NotationImpl(CoreDocumentImpl ownerDoc, String name) {
+ super(ownerDoc);
+ this.name = name;
+ }
+
+ //
+ // Node methods
+ //
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public short getNodeType() {
+ return Node.NOTATION_NODE;
+ }
+
+ /**
+ * Returns the notation name
+ */
+ public String getNodeName() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return name;
+ }
+
+ //
+ // Notation methods
+ //
+
+ /**
+ * The Public Identifier for this Notation. If no public identifier
+ * was specified, this will be null.
+ */
+ public String getPublicId() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return publicId;
+
+ } // getPublicId():String
+
+ /**
+ * The System Identifier for this Notation. If no system identifier
+ * was specified, this will be null.
+ */
+ public String getSystemId() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return systemId;
+
+ } // getSystemId():String
+
+ //
+ // Public methods
+ //
+
+ /**
+ * NON-DOM: The Public Identifier for this Notation. If no public
+ * identifier was specified, this will be null.
+ */
+ public void setPublicId(String id) {
+
+ if (isReadOnly()) {
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null));
+ }
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ publicId = id;
+
+ } // setPublicId(String)
+
+ /**
+ * NON-DOM: The System Identifier for this Notation. If no system
+ * identifier was specified, this will be null.
+ */
+ public void setSystemId(String id) {
+
+ if(isReadOnly()) {
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null));
+ }
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ systemId = id;
+
+ } // setSystemId(String)
+
+
+ /**
+ * Returns the absolute base URI of this node or null if the implementation
+ * wasn't able to obtain an absolute URI. Note: If the URI is malformed, a
+ * null is returned.
+ *
+ * @return The absolute base URI of this node or null.
+ * @since DOM Level 3
+ */
+ public String getBaseURI() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (baseURI != null && baseURI.length() != 0 ) {// attribute value is always empty string
+ try {
+ return new URI(baseURI).toString();
+ }
+ catch (org.apache.xerces.util.URI.MalformedURIException e){
+ // REVISIT: what should happen in this case?
+ return null;
+ }
+ }
+ return baseURI;
+ }
+
+ /** NON-DOM: set base uri*/
+ public void setBaseURI(String uri){
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ baseURI = uri;
+ }
+
+} // class NotationImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/ObjectFactory.java b/resources/xerces2-j-src/org/apache/xerces/dom/ObjectFactory.java
new file mode 100644
index 0000000..11eebe2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/ObjectFactory.java
@@ -0,0 +1,545 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Properties;
+
+/**
+ * This class is duplicated for each JAXP subpackage so keep it in sync.
+ * It is package private and therefore is not exposed as part of the JAXP
+ * API.
+ *
+ * This code is designed to implement the JAXP 1.1 spec pluggability
+ * feature and is designed to run on JDK version 1.1 and
+ * later, and to compile on JDK 1.2 and onward.
+ * The code also runs both as part of an unbundled jar file and
+ * when bundled as part of the JDK.
+ *
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+final class ObjectFactory {
+
+ //
+ // Constants
+ //
+
+ // name of default properties file to look for in JDK's jre/lib directory
+ private static final String DEFAULT_PROPERTIES_FILENAME = "xerces.properties";
+
+ /** Set to true for debugging */
+ private static final boolean DEBUG = isDebugEnabled();
+
+ /**
+ * Default columns per line.
+ */
+ private static final int DEFAULT_LINE_LENGTH = 80;
+
+ /** cache the contents of the xerces.properties file.
+ * Until an attempt has been made to read this file, this will
+ * be null; if the file does not exist or we encounter some other error
+ * during the read, this will be empty.
+ */
+ private static Properties fXercesProperties = null;
+
+ /***
+ * Cache the time stamp of the xerces.properties file so
+ * that we know if it's been modified and can invalidate
+ * the cache when necessary.
+ */
+ private static long fLastModified = -1;
+
+ //
+ // static methods
+ //
+
+ /**
+ * Finds the implementation Class object in the specified order. The
+ * specified order is the following:
+ *
+ * - query the system property using
System.getProperty
+ * - read
META-INF/services/factoryId file
+ * - use fallback classname
+ *
+ *
+ * @return Class object of factory, never null
+ *
+ * @param factoryId Name of the factory to find, same as
+ * a property name
+ * @param fallbackClassName Implementation class name, if nothing else
+ * is found. Use null to mean no fallback.
+ *
+ * @exception ObjectFactory.ConfigurationError
+ */
+ static Object createObject(String factoryId, String fallbackClassName)
+ throws ConfigurationError {
+ return createObject(factoryId, null, fallbackClassName);
+ } // createObject(String,String):Object
+
+ /**
+ * Finds the implementation Class object in the specified order. The
+ * specified order is the following:
+ *
+ * - query the system property using
System.getProperty
+ * - read
$java.home/lib/propertiesFilename file
+ * - read
META-INF/services/factoryId file
+ * - use fallback classname
+ *
+ *
+ * @return Class object of factory, never null
+ *
+ * @param factoryId Name of the factory to find, same as
+ * a property name
+ * @param propertiesFilename The filename in the $java.home/lib directory
+ * of the properties file. If none specified,
+ * ${java.home}/lib/xerces.properties will be used.
+ * @param fallbackClassName Implementation class name, if nothing else
+ * is found. Use null to mean no fallback.
+ *
+ * @exception ObjectFactory.ConfigurationError
+ */
+ static Object createObject(String factoryId,
+ String propertiesFilename,
+ String fallbackClassName)
+ throws ConfigurationError
+ {
+ if (DEBUG) debugPrintln("debug is on");
+
+ ClassLoader cl = findClassLoader();
+
+ // Use the system property first
+ try {
+ String systemProp = SecuritySupport.getSystemProperty(factoryId);
+ if (systemProp != null && systemProp.length() > 0) {
+ if (DEBUG) debugPrintln("found system property, value=" + systemProp);
+ return newInstance(systemProp, cl, true);
+ }
+ } catch (SecurityException se) {
+ // Ignore and continue w/ next location
+ }
+
+ // Try to read from propertiesFilename, or $java.home/lib/xerces.properties
+ String factoryClassName = null;
+ // no properties file name specified; use $JAVA_HOME/lib/xerces.properties:
+ if (propertiesFilename == null) {
+ File propertiesFile = null;
+ boolean propertiesFileExists = false;
+ try {
+ String javah = SecuritySupport.getSystemProperty("java.home");
+ propertiesFilename = javah + File.separator +
+ "lib" + File.separator + DEFAULT_PROPERTIES_FILENAME;
+ propertiesFile = new File(propertiesFilename);
+ propertiesFileExists = SecuritySupport.getFileExists(propertiesFile);
+ } catch (SecurityException e) {
+ // try again...
+ fLastModified = -1;
+ fXercesProperties = null;
+ }
+
+ synchronized (ObjectFactory.class) {
+ boolean loadProperties = false;
+ FileInputStream fis = null;
+ try {
+ // file existed last time
+ if(fLastModified >= 0) {
+ if(propertiesFileExists &&
+ (fLastModified < (fLastModified = SecuritySupport.getLastModified(propertiesFile)))) {
+ loadProperties = true;
+ } else {
+ // file has stopped existing...
+ if(!propertiesFileExists) {
+ fLastModified = -1;
+ fXercesProperties = null;
+ } // else, file wasn't modified!
+ }
+ } else {
+ // file has started to exist:
+ if(propertiesFileExists) {
+ loadProperties = true;
+ fLastModified = SecuritySupport.getLastModified(propertiesFile);
+ } // else, nothing's changed
+ }
+ if(loadProperties) {
+ // must never have attempted to read xerces.properties before (or it's outdeated)
+ fXercesProperties = new Properties();
+ fis = SecuritySupport.getFileInputStream(propertiesFile);
+ fXercesProperties.load(fis);
+ }
+ } catch (Exception x) {
+ fXercesProperties = null;
+ fLastModified = -1;
+ // assert(x instanceof FileNotFoundException
+ // || x instanceof SecurityException)
+ // In both cases, ignore and continue w/ next location
+ }
+ finally {
+ // try to close the input stream if one was opened.
+ if (fis != null) {
+ try {
+ fis.close();
+ }
+ // Ignore the exception.
+ catch (IOException exc) {}
+ }
+ }
+ }
+ if(fXercesProperties != null) {
+ factoryClassName = fXercesProperties.getProperty(factoryId);
+ }
+ } else {
+ FileInputStream fis = null;
+ try {
+ fis = SecuritySupport.getFileInputStream(new File(propertiesFilename));
+ Properties props = new Properties();
+ props.load(fis);
+ factoryClassName = props.getProperty(factoryId);
+ } catch (Exception x) {
+ // assert(x instanceof FileNotFoundException
+ // || x instanceof SecurityException)
+ // In both cases, ignore and continue w/ next location
+ }
+ finally {
+ // try to close the input stream if one was opened.
+ if (fis != null) {
+ try {
+ fis.close();
+ }
+ // Ignore the exception.
+ catch (IOException exc) {}
+ }
+ }
+ }
+ if (factoryClassName != null) {
+ if (DEBUG) debugPrintln("found in " + propertiesFilename + ", value=" + factoryClassName);
+ return newInstance(factoryClassName, cl, true);
+ }
+
+ // Try Jar Service Provider Mechanism
+ Object provider = findJarServiceProvider(factoryId);
+ if (provider != null) {
+ return provider;
+ }
+
+ if (fallbackClassName == null) {
+ throw new ConfigurationError(
+ "Provider for " + factoryId + " cannot be found", null);
+ }
+
+ if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName);
+ return newInstance(fallbackClassName, cl, true);
+ } // createObject(String,String,String):Object
+
+ //
+ // Private static methods
+ //
+
+ /** Returns true if debug has been enabled. */
+ private static boolean isDebugEnabled() {
+ try {
+ String val = SecuritySupport.getSystemProperty("xerces.debug");
+ // Allow simply setting the prop to turn on debug
+ return (val != null && (!"false".equals(val)));
+ }
+ catch (SecurityException se) {}
+ return false;
+ } // isDebugEnabled()
+
+ /** Prints a message to standard error if debugging is enabled. */
+ private static void debugPrintln(String msg) {
+ if (DEBUG) {
+ System.err.println("XERCES: " + msg);
+ }
+ } // debugPrintln(String)
+
+ /**
+ * Figure out which ClassLoader to use. For JDK 1.2 and later use
+ * the context ClassLoader.
+ */
+ static ClassLoader findClassLoader()
+ throws ConfigurationError
+ {
+ // Figure out which ClassLoader to use for loading the provider
+ // class. If there is a Context ClassLoader then use it.
+ ClassLoader context = SecuritySupport.getContextClassLoader();
+ ClassLoader system = SecuritySupport.getSystemClassLoader();
+
+ ClassLoader chain = system;
+ while (true) {
+ if (context == chain) {
+ // Assert: we are on JDK 1.1 or we have no Context ClassLoader
+ // or any Context ClassLoader in chain of system classloader
+ // (including extension ClassLoader) so extend to widest
+ // ClassLoader (always look in system ClassLoader if Xerces
+ // is in boot/extension/system classpath and in current
+ // ClassLoader otherwise); normal classloaders delegate
+ // back to system ClassLoader first so this widening doesn't
+ // change the fact that context ClassLoader will be consulted
+ ClassLoader current = ObjectFactory.class.getClassLoader();
+
+ chain = system;
+ while (true) {
+ if (current == chain) {
+ // Assert: Current ClassLoader in chain of
+ // boot/extension/system ClassLoaders
+ return system;
+ }
+ if (chain == null) {
+ break;
+ }
+ chain = SecuritySupport.getParentClassLoader(chain);
+ }
+
+ // Assert: Current ClassLoader not in chain of
+ // boot/extension/system ClassLoaders
+ return current;
+ }
+
+ if (chain == null) {
+ // boot ClassLoader reached
+ break;
+ }
+
+ // Check for any extension ClassLoaders in chain up to
+ // boot ClassLoader
+ chain = SecuritySupport.getParentClassLoader(chain);
+ };
+
+ // Assert: Context ClassLoader not in chain of
+ // boot/extension/system ClassLoaders
+ return context;
+ } // findClassLoader():ClassLoader
+
+ /**
+ * Create an instance of a class using the specified ClassLoader
+ */
+ static Object newInstance(String className, ClassLoader cl,
+ boolean doFallback)
+ throws ConfigurationError
+ {
+ // assert(className != null);
+ try{
+ Class providerClass = findProviderClass(className, cl, doFallback);
+ Object instance = providerClass.newInstance();
+ if (DEBUG) debugPrintln("created new instance of " + providerClass +
+ " using ClassLoader: " + cl);
+ return instance;
+ } catch (ClassNotFoundException x) {
+ throw new ConfigurationError(
+ "Provider " + className + " not found", x);
+ } catch (Exception x) {
+ throw new ConfigurationError(
+ "Provider " + className + " could not be instantiated: " + x,
+ x);
+ }
+ }
+
+ /**
+ * Find a Class using the specified ClassLoader
+ */
+ static Class findProviderClass(String className, ClassLoader cl,
+ boolean doFallback)
+ throws ClassNotFoundException, ConfigurationError
+ {
+ //throw security exception if the calling thread is not allowed to access the package
+ //restrict the access to package as specified in java.security policy
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ final int lastDot = className.lastIndexOf('.');
+ String packageName = className;
+ if (lastDot != -1) packageName = className.substring(0, lastDot);
+ security.checkPackageAccess(packageName);
+ }
+ Class providerClass;
+ if (cl == null) {
+ // XXX Use the bootstrap ClassLoader. There is no way to
+ // load a class using the bootstrap ClassLoader that works
+ // in both JDK 1.1 and Java 2. However, this should still
+ // work b/c the following should be true:
+ //
+ // (cl == null) iff current ClassLoader == null
+ //
+ // Thus Class.forName(String) will use the current
+ // ClassLoader which will be the bootstrap ClassLoader.
+ providerClass = Class.forName(className);
+ } else {
+ try {
+ providerClass = cl.loadClass(className);
+ } catch (ClassNotFoundException x) {
+ if (doFallback) {
+ // Fall back to current classloader
+ ClassLoader current = ObjectFactory.class.getClassLoader();
+ if (current == null) {
+ providerClass = Class.forName(className);
+ } else if (cl != current) {
+ cl = current;
+ providerClass = cl.loadClass(className);
+ } else {
+ throw x;
+ }
+ } else {
+ throw x;
+ }
+ }
+ }
+
+ return providerClass;
+ }
+
+ /*
+ * Try to find provider using Jar Service Provider Mechanism
+ *
+ * @return instance of provider class if found or null
+ */
+ private static Object findJarServiceProvider(String factoryId)
+ throws ConfigurationError
+ {
+ String serviceId = "META-INF/services/" + factoryId;
+ InputStream is = null;
+
+ // First try the Context ClassLoader
+ ClassLoader cl = findClassLoader();
+
+ is = SecuritySupport.getResourceAsStream(cl, serviceId);
+
+ // If no provider found then try the current ClassLoader
+ if (is == null) {
+ ClassLoader current = ObjectFactory.class.getClassLoader();
+ if (cl != current) {
+ cl = current;
+ is = SecuritySupport.getResourceAsStream(cl, serviceId);
+ }
+ }
+
+ if (is == null) {
+ // No provider found
+ return null;
+ }
+
+ if (DEBUG) debugPrintln("found jar resource=" + serviceId +
+ " using ClassLoader: " + cl);
+
+ // Read the service provider name in UTF-8 as specified in
+ // the jar spec. Unfortunately this fails in Microsoft
+ // VJ++, which does not implement the UTF-8
+ // encoding. Theoretically, we should simply let it fail in
+ // that case, since the JVM is obviously broken if it
+ // doesn't support such a basic standard. But since there
+ // are still some users attempting to use VJ++ for
+ // development, we have dropped in a fallback which makes a
+ // second attempt using the platform's default encoding. In
+ // VJ++ this is apparently ASCII, which is a subset of
+ // UTF-8... and since the strings we'll be reading here are
+ // also primarily limited to the 7-bit ASCII range (at
+ // least, in English versions), this should work well
+ // enough to keep us on the air until we're ready to
+ // officially decommit from VJ++. [Edited comment from
+ // jkesselm]
+ BufferedReader rd;
+ try {
+ rd = new BufferedReader(new InputStreamReader(is, "UTF-8"), DEFAULT_LINE_LENGTH);
+ } catch (java.io.UnsupportedEncodingException e) {
+ rd = new BufferedReader(new InputStreamReader(is), DEFAULT_LINE_LENGTH);
+ }
+
+ String factoryClassName = null;
+ try {
+ // XXX Does not handle all possible input as specified by the
+ // Jar Service Provider specification
+ factoryClassName = rd.readLine();
+ } catch (IOException x) {
+ // No provider found
+ return null;
+ }
+ finally {
+ try {
+ // try to close the reader.
+ rd.close();
+ }
+ // Ignore the exception.
+ catch (IOException exc) {}
+ }
+
+ if (factoryClassName != null &&
+ ! "".equals(factoryClassName)) {
+ if (DEBUG) debugPrintln("found in resource, value="
+ + factoryClassName);
+
+ // Note: here we do not want to fall back to the current
+ // ClassLoader because we want to avoid the case where the
+ // resource file was found using one ClassLoader and the
+ // provider class was instantiated using a different one.
+ return newInstance(factoryClassName, cl, false);
+ }
+
+ // No provider found
+ return null;
+ }
+
+ //
+ // Classes
+ //
+
+ /**
+ * A configuration error.
+ */
+ static final class ConfigurationError
+ extends Error {
+
+ /** Serialization version. */
+ static final long serialVersionUID = 1914065341994951202L;
+
+ //
+ // Data
+ //
+
+ /** Exception. */
+ private Exception exception;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Construct a new instance with the specified detail string and
+ * exception.
+ */
+ ConfigurationError(String msg, Exception x) {
+ super(msg);
+ this.exception = x;
+ } // (String,Exception)
+
+ //
+ // methods
+ //
+
+ /** Returns the exception associated to this error. */
+ Exception getException() {
+ return exception;
+ } // getException():Exception
+
+ } // class ConfigurationError
+
+} // class ObjectFactory
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/PSVIAttrNSImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/PSVIAttrNSImpl.java
new file mode 100644
index 0000000..eb05b5d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/PSVIAttrNSImpl.java
@@ -0,0 +1,285 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.xerces.impl.dv.ValidatedInfo;
+import org.apache.xerces.impl.xs.AttributePSVImpl;
+import org.apache.xerces.impl.xs.util.StringListImpl;
+import org.apache.xerces.xs.AttributePSVI;
+import org.apache.xerces.xs.ItemPSVI;
+import org.apache.xerces.xs.ShortList;
+import org.apache.xerces.xs.StringList;
+import org.apache.xerces.xs.XSAttributeDeclaration;
+import org.apache.xerces.xs.XSSimpleTypeDefinition;
+import org.apache.xerces.xs.XSTypeDefinition;
+import org.apache.xerces.xs.XSValue;
+
+/**
+ * Attribute namespace implementation; stores PSVI attribute items.
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class PSVIAttrNSImpl extends AttrNSImpl implements AttributePSVI {
+
+ /** Serialization version. */
+ static final long serialVersionUID = -3241738699421018889L;
+
+ /**
+ * Construct an attribute node.
+ */
+ public PSVIAttrNSImpl(CoreDocumentImpl ownerDocument, String namespaceURI,
+ String qualifiedName, String localName) {
+ super(ownerDocument, namespaceURI, qualifiedName, localName);
+ }
+
+ /**
+ * Construct an attribute node.
+ */
+ public PSVIAttrNSImpl(CoreDocumentImpl ownerDocument, String namespaceURI,
+ String qualifiedName) {
+ super(ownerDocument, namespaceURI, qualifiedName);
+ }
+
+ /** attribute declaration */
+ protected XSAttributeDeclaration fDeclaration = null;
+
+ /** type of attribute, simpleType */
+ protected XSTypeDefinition fTypeDecl = null;
+
+ /** If this attribute was explicitly given a
+ * value in the original document, this is true; otherwise, it is false */
+ protected boolean fSpecified = true;
+
+ /** Schema value */
+ protected ValidatedInfo fValue = new ValidatedInfo();
+
+ /** validation attempted: none, partial, full */
+ protected short fValidationAttempted = AttributePSVI.VALIDATION_NONE;
+
+ /** validity: valid, invalid, unknown */
+ protected short fValidity = AttributePSVI.VALIDITY_NOTKNOWN;
+
+ /** error codes */
+ protected StringList fErrorCodes = null;
+
+ /** error messages */
+ protected StringList fErrorMessages = null;
+
+ /** validation context: could be QName or XPath expression*/
+ protected String fValidationContext = null;
+
+ //
+ // AttributePSVI methods
+ //
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#constant()
+ */
+ public ItemPSVI constant() {
+ return new AttributePSVImpl(true, this);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#isConstant()
+ */
+ public boolean isConstant() {
+ return false;
+ }
+
+ /**
+ * [schema default]
+ *
+ * @return The canonical lexical representation of the declaration's {value constraint} value.
+ * @see XML Schema Part 1: Structures [schema normalized value]
+ * @return the normalized value of this item after validation
+ */
+ public String getSchemaNormalizedValue() {
+ return fValue.getNormalizedValue();
+ }
+
+ /**
+ * [schema specified]
+ * @see XML Schema Part 1: Structures [schema specified]
+ * @return false value was specified in schema, true value comes from the infoset
+ */
+ public boolean getIsSchemaSpecified() {
+ return fSpecified;
+ }
+
+
+ /**
+ * Determines the extent to which the document has been validated
+ *
+ * @return return the [validation attempted] property. The possible values are
+ * NO_VALIDATION, PARTIAL_VALIDATION and FULL_VALIDATION
+ */
+ public short getValidationAttempted() {
+ return fValidationAttempted;
+ }
+
+ /**
+ * Determine the validity of the node with respect
+ * to the validation being attempted
+ *
+ * @return return the [validity] property. Possible values are:
+ * UNKNOWN_VALIDITY, INVALID_VALIDITY, VALID_VALIDITY
+ */
+ public short getValidity() {
+ return fValidity;
+ }
+
+ /**
+ * A list of error codes generated from validation attempts.
+ * Need to find all the possible subclause reports that need reporting
+ *
+ * @return list of error codes
+ */
+ public StringList getErrorCodes() {
+ if (fErrorCodes != null) {
+ return fErrorCodes;
+ }
+ return StringListImpl.EMPTY_LIST;
+ }
+
+ /**
+ * A list of error messages generated from the validation attempt or
+ * an empty StringList if no errors occurred during the
+ * validation attempt. The indices of error messages in this list are
+ * aligned with those in the [schema error code] list.
+ */
+ public StringList getErrorMessages() {
+ if (fErrorMessages != null) {
+ return fErrorMessages;
+ }
+ return StringListImpl.EMPTY_LIST;
+ }
+
+ // This is the only information we can provide in a pipeline.
+ public String getValidationContext() {
+ return fValidationContext;
+ }
+
+ /**
+ * An item isomorphic to the type definition used to validate this element.
+ *
+ * @return a type declaration
+ */
+ public XSTypeDefinition getTypeDefinition() {
+ return fTypeDecl;
+ }
+
+ /**
+ * If and only if that type definition is a simple type definition
+ * with {variety} union, or a complex type definition whose {content type}
+ * is a simple thype definition with {variety} union, then an item isomorphic
+ * to that member of the union's {member type definitions} which actually
+ * validated the element item's normalized value.
+ *
+ * @return a simple type declaration
+ */
+ public XSSimpleTypeDefinition getMemberTypeDefinition() {
+ return fValue.getMemberTypeDefinition();
+ }
+
+ /**
+ * An item isomorphic to the attribute declaration used to validate
+ * this attribute.
+ *
+ * @return an attribute declaration
+ */
+ public XSAttributeDeclaration getAttributeDeclaration() {
+ return fDeclaration;
+ }
+
+ /**
+ * Copy PSVI properties from another psvi item.
+ *
+ * @param attr the source of attribute PSVI items
+ */
+ public void setPSVI(AttributePSVI attr) {
+ this.fDeclaration = attr.getAttributeDeclaration();
+ this.fValidationContext = attr.getValidationContext();
+ this.fValidity = attr.getValidity();
+ this.fValidationAttempted = attr.getValidationAttempted();
+ this.fErrorCodes = attr.getErrorCodes();
+ this.fErrorMessages = attr.getErrorMessages();
+ this.fValue.copyFrom(attr.getSchemaValue());
+ this.fTypeDecl = attr.getTypeDefinition();
+ this.fSpecified = attr.getIsSchemaSpecified();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getActualNormalizedValue()
+ */
+ public Object getActualNormalizedValue() {
+ return fValue.getActualValue();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getActualNormalizedValueType()
+ */
+ public short getActualNormalizedValueType() {
+ return fValue.getActualValueType();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getItemValueTypes()
+ */
+ public ShortList getItemValueTypes() {
+ return fValue.getListValueTypes();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getSchemaValue()
+ */
+ public XSValue getSchemaValue() {
+ return fValue;
+ }
+
+ // REVISIT: Forbid serialization of PSVI DOM until
+ // we support object serialization of grammars -- mrglavas
+
+ private void writeObject(ObjectOutputStream out)
+ throws IOException {
+ throw new NotSerializableException(getClass().getName());
+ }
+
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException {
+ throw new NotSerializableException(getClass().getName());
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/PSVIDOMImplementationImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/PSVIDOMImplementationImpl.java
new file mode 100644
index 0000000..3f6e391
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/PSVIDOMImplementationImpl.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.DocumentType;
+
+/**
+ * The DOMImplementation class is description of a particular
+ * implementation of the Document Object Model. As such its data is
+ * static, shared by all instances of this implementation.
+ *
+ * The DOM API requires that it be a real object rather than static
+ * methods. However, there's nothing that says it can't be a singleton,
+ * so that's how I've implemented it.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class PSVIDOMImplementationImpl extends DOMImplementationImpl {
+
+ //
+ // Data
+ //
+
+ // static
+
+ /** Dom implementation singleton. */
+ static final PSVIDOMImplementationImpl singleton = new PSVIDOMImplementationImpl();
+
+ //
+ // Public methods
+ //
+
+ /** NON-DOM: Obtain and return the single shared object */
+ public static DOMImplementation getDOMImplementation() {
+ return singleton;
+ }
+
+ //
+ // DOMImplementation methods
+ //
+
+ /**
+ * Test if the DOM implementation supports a specific "feature" --
+ * currently meaning language and level thereof.
+ *
+ * @param feature The package name of the feature to test.
+ * In Level 1, supported values are "HTML" and "XML" (case-insensitive).
+ * At this writing, org.apache.xerces.dom supports only XML.
+ *
+ * @param version The version number of the feature being tested.
+ * This is interpreted as "Version of the DOM API supported for the
+ * specified Feature", and in Level 1 should be "1.0"
+ *
+ * @return true iff this implementation is compatable with the specified
+ * feature and version.
+ */
+ public boolean hasFeature(String feature, String version) {
+ return super.hasFeature(feature, version) ||
+ feature.equalsIgnoreCase("psvi");
+ } // hasFeature(String,String):boolean
+
+ //
+ // Protected methods
+ //
+
+ protected CoreDocumentImpl createDocument(DocumentType doctype) {
+ return new PSVIDocumentImpl(doctype);
+ }
+
+} // class PSVIDOMImplementationImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/PSVIDocumentImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/PSVIDocumentImpl.java
new file mode 100644
index 0000000..c448604
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/PSVIDocumentImpl.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMConfiguration;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.UserDataHandler;
+
+/**
+ * Our own document implementation, which knows how to create an element
+ * with PSVI information.
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class PSVIDocumentImpl extends DocumentImpl {
+
+ /** Serialization version. */
+ static final long serialVersionUID = -8822220250676434522L;
+
+ /**
+ * Create a document.
+ */
+ public PSVIDocumentImpl() {
+ super();
+ }
+
+ /**
+ * For DOM2 support.
+ * The createDocument factory method is in DOMImplementation.
+ */
+ public PSVIDocumentImpl(DocumentType doctype) {
+ super(doctype);
+ }
+
+ /**
+ * Deep-clone a document, including fixing ownerDoc for the cloned
+ * children. Note that this requires bypassing the WRONG_DOCUMENT_ERR
+ * protection. I've chosen to implement it by calling importNode
+ * which is DOM Level 2.
+ *
+ * @return org.w3c.dom.Node
+ * @param deep boolean, iff true replicate children
+ */
+ public Node cloneNode(boolean deep) {
+
+ PSVIDocumentImpl newdoc = new PSVIDocumentImpl();
+ callUserDataHandlers(this, newdoc, UserDataHandler.NODE_CLONED);
+ cloneNode(newdoc, deep);
+
+ // experimental
+ newdoc.mutationEvents = mutationEvents;
+
+ return newdoc;
+
+ } // cloneNode(boolean):Node
+
+ /**
+ * Retrieve information describing the abilities of this particular
+ * DOM implementation. Intended to support applications that may be
+ * using DOMs retrieved from several different sources, potentially
+ * with different underlying representations.
+ */
+ public DOMImplementation getImplementation() {
+ // Currently implemented as a singleton, since it's hardcoded
+ // information anyway.
+ return PSVIDOMImplementationImpl.getDOMImplementation();
+ }
+
+ /**
+ * Create an element with PSVI information
+ */
+ public Element createElementNS(String namespaceURI, String qualifiedName)
+ throws DOMException {
+ return new PSVIElementNSImpl(this, namespaceURI, qualifiedName);
+ }
+
+ /**
+ * Create an element with PSVI information
+ */
+ public Element createElementNS(String namespaceURI, String qualifiedName,
+ String localpart) throws DOMException {
+ return new PSVIElementNSImpl(this, namespaceURI, qualifiedName, localpart);
+ }
+
+ /**
+ * Create an attribute with PSVI information
+ */
+ public Attr createAttributeNS(String namespaceURI, String qualifiedName)
+ throws DOMException {
+ return new PSVIAttrNSImpl(this, namespaceURI, qualifiedName);
+ }
+
+ /**
+ * Create an attribute with PSVI information
+ */
+ public Attr createAttributeNS(String namespaceURI, String qualifiedName,
+ String localName) throws DOMException {
+ return new PSVIAttrNSImpl(this, namespaceURI, qualifiedName, localName);
+ }
+
+ /**
+ *
+ * The configuration used when Document.normalizeDocument is
+ * invoked.
+ * @since DOM Level 3
+ */
+ public DOMConfiguration getDomConfig(){
+ super.getDomConfig();
+ return fConfiguration;
+ }
+
+ // REVISIT: Forbid serialization of PSVI DOM until
+ // we support object serialization of grammars -- mrglavas
+
+ private void writeObject(ObjectOutputStream out)
+ throws IOException {
+ throw new NotSerializableException(getClass().getName());
+ }
+
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException {
+ throw new NotSerializableException(getClass().getName());
+ }
+
+} // class PSVIDocumentImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/PSVIElementNSImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/PSVIElementNSImpl.java
new file mode 100644
index 0000000..3a6aec2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/PSVIElementNSImpl.java
@@ -0,0 +1,336 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.xerces.impl.dv.ValidatedInfo;
+import org.apache.xerces.impl.xs.ElementPSVImpl;
+import org.apache.xerces.impl.xs.util.StringListImpl;
+import org.apache.xerces.xs.ElementPSVI;
+import org.apache.xerces.xs.ItemPSVI;
+import org.apache.xerces.xs.ShortList;
+import org.apache.xerces.xs.StringList;
+import org.apache.xerces.xs.XSComplexTypeDefinition;
+import org.apache.xerces.xs.XSElementDeclaration;
+import org.apache.xerces.xs.XSModel;
+import org.apache.xerces.xs.XSNotationDeclaration;
+import org.apache.xerces.xs.XSSimpleTypeDefinition;
+import org.apache.xerces.xs.XSTypeDefinition;
+import org.apache.xerces.xs.XSValue;
+
+/**
+ * Element namespace implementation; stores PSVI element items.
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class PSVIElementNSImpl extends ElementNSImpl implements ElementPSVI {
+
+ /** Serialization version. */
+ static final long serialVersionUID = 6815489624636016068L;
+
+ /**
+ * Construct an element node.
+ */
+ public PSVIElementNSImpl(CoreDocumentImpl ownerDocument, String namespaceURI,
+ String qualifiedName, String localName) {
+ super(ownerDocument, namespaceURI, qualifiedName, localName);
+ }
+
+ /**
+ * Construct an element node.
+ */
+ public PSVIElementNSImpl(CoreDocumentImpl ownerDocument, String namespaceURI,
+ String qualifiedName) {
+ super(ownerDocument, namespaceURI, qualifiedName);
+ }
+
+ /** element declaration */
+ protected XSElementDeclaration fDeclaration = null;
+
+ /** type of element, could be xsi:type */
+ protected XSTypeDefinition fTypeDecl = null;
+
+ /** true if clause 3.2 of Element Locally Valid (Element) (3.3.4)
+ * is satisfied, otherwise false
+ */
+ protected boolean fNil = false;
+
+ /** false if the element value was provided by the schema; true otherwise.
+ */
+ protected boolean fSpecified = true;
+
+ /** Schema value */
+ protected ValidatedInfo fValue = new ValidatedInfo();
+
+ /** http://www.w3.org/TR/xmlschema-1/#e-notation*/
+ protected XSNotationDeclaration fNotation = null;
+
+ /** validation attempted: none, partial, full */
+ protected short fValidationAttempted = ElementPSVI.VALIDATION_NONE;
+
+ /** validity: valid, invalid, unknown */
+ protected short fValidity = ElementPSVI.VALIDITY_NOTKNOWN;
+
+ /** error codes */
+ protected StringList fErrorCodes = null;
+
+ /** error messages */
+ protected StringList fErrorMessages = null;
+
+ /** validation context: could be QName or XPath expression*/
+ protected String fValidationContext = null;
+
+ /** the schema information property */
+ protected XSModel fSchemaInformation = null;
+
+ //
+ // ElementPSVI methods
+ //
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#constant()
+ */
+ public ItemPSVI constant() {
+ return new ElementPSVImpl(true, this);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#isConstant()
+ */
+ public boolean isConstant() {
+ return false;
+ }
+
+ /**
+ * [schema default]
+ *
+ * @return The canonical lexical representation of the declaration's {value constraint} value.
+ * @see XML Schema Part 1: Structures [schema normalized value]
+ * @return the normalized value of this item after validation
+ */
+ public String getSchemaNormalizedValue() {
+ return fValue.getNormalizedValue();
+ }
+
+ /**
+ * [schema specified]
+ * @see XML Schema Part 1: Structures [schema specified]
+ * @return false value was specified in schema, true value comes from the infoset
+ */
+ public boolean getIsSchemaSpecified() {
+ return fSpecified;
+ }
+
+ /**
+ * Determines the extent to which the document has been validated
+ *
+ * @return return the [validation attempted] property. The possible values are
+ * NO_VALIDATION, PARTIAL_VALIDATION and FULL_VALIDATION
+ */
+ public short getValidationAttempted() {
+ return fValidationAttempted;
+ }
+
+ /**
+ * Determine the validity of the node with respect
+ * to the validation being attempted
+ *
+ * @return return the [validity] property. Possible values are:
+ * UNKNOWN_VALIDITY, INVALID_VALIDITY, VALID_VALIDITY
+ */
+ public short getValidity() {
+ return fValidity;
+ }
+
+ /**
+ * A list of error codes generated from validation attempts.
+ * Need to find all the possible subclause reports that need reporting
+ *
+ * @return Array of error codes
+ */
+ public StringList getErrorCodes() {
+ if (fErrorCodes != null) {
+ return fErrorCodes;
+ }
+ return StringListImpl.EMPTY_LIST;
+ }
+
+ /**
+ * A list of error messages generated from the validation attempt or
+ * an empty StringList if no errors occurred during the
+ * validation attempt. The indices of error messages in this list are
+ * aligned with those in the [schema error code] list.
+ */
+ public StringList getErrorMessages() {
+ if (fErrorMessages != null) {
+ return fErrorMessages;
+ }
+ return StringListImpl.EMPTY_LIST;
+ }
+
+ // This is the only information we can provide in a pipeline.
+ public String getValidationContext() {
+ return fValidationContext;
+ }
+
+ /**
+ * [nil]
+ * @see XML Schema Part 1: Structures [notation]
+ * @return The notation declaration.
+ */
+ public XSNotationDeclaration getNotation() {
+ return fNotation;
+ }
+
+ /**
+ * An item isomorphic to the type definition used to validate this element.
+ *
+ * @return a type declaration
+ */
+ public XSTypeDefinition getTypeDefinition() {
+ return fTypeDecl;
+ }
+
+ /**
+ * If and only if that type definition is a simple type definition
+ * with {variety} union, or a complex type definition whose {content type}
+ * is a simple thype definition with {variety} union, then an item isomorphic
+ * to that member of the union's {member type definitions} which actually
+ * validated the element item's normalized value.
+ *
+ * @return a simple type declaration
+ */
+ public XSSimpleTypeDefinition getMemberTypeDefinition() {
+ return fValue.getMemberTypeDefinition();
+ }
+
+ /**
+ * An item isomorphic to the element declaration used to validate
+ * this element.
+ *
+ * @return an element declaration
+ */
+ public XSElementDeclaration getElementDeclaration() {
+ return fDeclaration;
+ }
+
+ /**
+ * [schema information]
+ * @see XML Schema Part 1: Structures [schema information]
+ * @return The schema information property if it's the validation root,
+ * null otherwise.
+ */
+ public XSModel getSchemaInformation() {
+ return fSchemaInformation;
+ }
+
+ /**
+ * Copy PSVI properties from another psvi item.
+ *
+ * @param elem the source of element PSVI items
+ */
+ public void setPSVI(ElementPSVI elem) {
+ this.fDeclaration = elem.getElementDeclaration();
+ this.fNotation = elem.getNotation();
+ this.fValidationContext = elem.getValidationContext();
+ this.fTypeDecl = elem.getTypeDefinition();
+ this.fSchemaInformation = elem.getSchemaInformation();
+ this.fValidity = elem.getValidity();
+ this.fValidationAttempted = elem.getValidationAttempted();
+ this.fErrorCodes = elem.getErrorCodes();
+ this.fErrorMessages = elem.getErrorMessages();
+ if (fTypeDecl instanceof XSSimpleTypeDefinition ||
+ fTypeDecl instanceof XSComplexTypeDefinition &&
+ ((XSComplexTypeDefinition)fTypeDecl).getContentType() == XSComplexTypeDefinition.CONTENTTYPE_SIMPLE) {
+ this.fValue.copyFrom(elem.getSchemaValue());
+ }
+ else {
+ this.fValue.reset();
+ }
+ this.fSpecified = elem.getIsSchemaSpecified();
+ this.fNil = elem.getNil();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getActualNormalizedValue()
+ */
+ public Object getActualNormalizedValue() {
+ return fValue.getActualValue();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getActualNormalizedValueType()
+ */
+ public short getActualNormalizedValueType() {
+ return fValue.getActualValueType();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getItemValueTypes()
+ */
+ public ShortList getItemValueTypes() {
+ return fValue.getListValueTypes();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getSchemaValue()
+ */
+ public XSValue getSchemaValue() {
+ return fValue;
+ }
+
+ // REVISIT: Forbid serialization of PSVI DOM until
+ // we support object serialization of grammars -- mrglavas
+
+ private void writeObject(ObjectOutputStream out)
+ throws IOException {
+ throw new NotSerializableException(getClass().getName());
+ }
+
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException {
+ throw new NotSerializableException(getClass().getName());
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/ParentNode.java b/resources/xerces2-j-src/org/apache/xerces/dom/ParentNode.java
new file mode 100644
index 0000000..1e3de89
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/ParentNode.java
@@ -0,0 +1,1031 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.UserDataHandler;
+
+/**
+ * ParentNode inherits from ChildNode and adds the capability of having child
+ * nodes. Not every node in the DOM can have children, so only nodes that can
+ * should inherit from this class and pay the price for it.
+ *
+ * ParentNode, just like NodeImpl, also implements NodeList, so it can
+ * return itself in response to the getChildNodes() query. This eliminiates
+ * the need for a separate ChildNodeList object. Note that this is an
+ * IMPLEMENTATION DETAIL; applications should _never_ assume that
+ * this identity exists. On the other hand, subclasses may need to override
+ * this, in case of conflicting names. This is the case for the classes
+ * HTMLSelectElementImpl and HTMLFormElementImpl of the HTML DOM.
+ *
+ * While we have a direct reference to the first child, the last child is
+ * stored as the previous sibling of the first child. First child nodes are
+ * marked as being so, and getNextSibling hides this fact.
+ * Note: Not all parent nodes actually need to also be a child. At some
+ * point we used to have ParentNode inheriting from NodeImpl and another class
+ * called ChildAndParentNode that inherited from ChildNode. But due to the lack
+ * of multiple inheritance a lot of code had to be duplicated which led to a
+ * maintenance nightmare. At the same time only a few nodes (Document,
+ * DocumentFragment, Entity, and Attribute) cannot be a child so the gain in
+ * memory wasn't really worth it. The only type for which this would be the
+ * case is Attribute, but we deal with there in another special way, so this is
+ * not applicable.
+ *
+ * This class doesn't directly support mutation events, however, it notifies
+ * the document when mutations are performed so that the document class do so.
+ *
+ * WARNING: Some of the code here is partially duplicated in
+ * AttrImpl, be careful to keep these two classes in sync!
+ *
+ * @xerces.internal
+ *
+ * @author Arnaud Le Hors, IBM
+ * @author Joe Kesselman, IBM
+ * @author Andy Clark, IBM
+ * @version $Id$
+ */
+public abstract class ParentNode
+ extends ChildNode {
+
+ /** Serialization version. */
+ static final long serialVersionUID = 2815829867152120872L;
+
+ /** Owner document. */
+ protected CoreDocumentImpl ownerDocument;
+
+ /** First child. */
+ protected ChildNode firstChild = null;
+
+ // transients
+
+ /** NodeList cache */
+ protected transient NodeListCache fNodeListCache = null;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * No public constructor; only subclasses of ParentNode should be
+ * instantiated, and those normally via a Document's factory methods
+ */
+ protected ParentNode(CoreDocumentImpl ownerDocument) {
+ super(ownerDocument);
+ this.ownerDocument = ownerDocument;
+ }
+
+ /** Constructor for serialization. */
+ public ParentNode() {}
+
+ //
+ // NodeList methods
+ //
+
+ /**
+ * Returns a duplicate of a given node. You can consider this a
+ * generic "copy constructor" for nodes. The newly returned object should
+ * be completely independent of the source object's subtree, so changes
+ * in one after the clone has been made will not affect the other.
+ *
+ * Example: Cloning a Text node will copy both the node and the text it
+ * contains.
+ *
+ * Example: Cloning something that has children -- Element or Attr, for
+ * example -- will _not_ clone those children unless a "deep clone"
+ * has been requested. A shallow clone of an Attr node will yield an
+ * empty Attr of the same name.
+ *
+ * NOTE: Clones will always be read/write, even if the node being cloned
+ * is read-only, to permit applications using only the DOM API to obtain
+ * editable copies of locked portions of the tree.
+ */
+ public Node cloneNode(boolean deep) {
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ ParentNode newnode = (ParentNode) super.cloneNode(deep);
+
+ // set owner document
+ newnode.ownerDocument = ownerDocument;
+
+ // Need to break the association w/ original kids
+ newnode.firstChild = null;
+
+ // invalidate cache for children NodeList
+ newnode.fNodeListCache = null;
+
+ // Then, if deep, clone the kids too.
+ if (deep) {
+ for (ChildNode child = firstChild;
+ child != null;
+ child = child.nextSibling) {
+ newnode.appendChild(child.cloneNode(true));
+ }
+ }
+
+ return newnode;
+
+ } // cloneNode(boolean):Node
+
+ /**
+ * Find the Document that this Node belongs to (the document in
+ * whose context the Node was created). The Node may or may not
+ * currently be part of that Document's actual contents.
+ */
+ public Document getOwnerDocument() {
+ return ownerDocument;
+ }
+
+ /**
+ * same as above but returns internal type and this one is not overridden
+ * by CoreDocumentImpl to return null
+ */
+ CoreDocumentImpl ownerDocument() {
+ return ownerDocument;
+ }
+
+ /**
+ * NON-DOM
+ * set the ownerDocument of this node and its children
+ */
+ protected void setOwnerDocument(CoreDocumentImpl doc) {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ super.setOwnerDocument(doc);
+ ownerDocument = doc;
+ for (ChildNode child = firstChild;
+ child != null; child = child.nextSibling) {
+ child.setOwnerDocument(doc);
+ }
+ }
+
+ /**
+ * Test whether this node has any children. Convenience shorthand
+ * for (Node.getFirstChild()!=null)
+ */
+ public boolean hasChildNodes() {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return firstChild != null;
+ }
+
+ /**
+ * Obtain a NodeList enumerating all children of this node. If there
+ * are none, an (initially) empty NodeList is returned.
+ *
+ * NodeLists are "live"; as children are added/removed the NodeList
+ * will immediately reflect those changes. Also, the NodeList refers
+ * to the actual nodes, so changes to those nodes made via the DOM tree
+ * will be reflected in the NodeList and vice versa.
+ *
+ * In this implementation, Nodes implement the NodeList interface and
+ * provide their own getChildNodes() support. Other DOMs may solve this
+ * differently.
+ */
+ public NodeList getChildNodes() {
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return this;
+
+ } // getChildNodes():NodeList
+
+ /** The first child of this Node, or null if none. */
+ public Node getFirstChild() {
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return firstChild;
+
+ } // getFirstChild():Node
+
+ /** The last child of this Node, or null if none. */
+ public Node getLastChild() {
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return lastChild();
+
+ } // getLastChild():Node
+
+ final ChildNode lastChild() {
+ // last child is stored as the previous sibling of first child
+ return firstChild != null ? firstChild.previousSibling : null;
+ }
+
+ final void lastChild(ChildNode node) {
+ // store lastChild as previous sibling of first child
+ if (firstChild != null) {
+ firstChild.previousSibling = node;
+ }
+ }
+
+ /**
+ * Move one or more node(s) to our list of children. Note that this
+ * implicitly removes them from their previous parent.
+ *
+ * @param newChild The Node to be moved to our subtree. As a
+ * convenience feature, inserting a DocumentNode will instead insert
+ * all its children.
+ *
+ * @param refChild Current child which newChild should be placed
+ * immediately before. If refChild is null, the insertion occurs
+ * after all existing Nodes, like appendChild().
+ *
+ * @return newChild, in its new state (relocated, or emptied in the case of
+ * DocumentNode.)
+ *
+ * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
+ * type that shouldn't be a child of this node, or if newChild is an
+ * ancestor of this node.
+ *
+ * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
+ * different owner document than we do.
+ *
+ * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
+ * this node.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
+ * read-only.
+ */
+ public Node insertBefore(Node newChild, Node refChild)
+ throws DOMException {
+ // Tail-call; optimizer should be able to do good things with.
+ return internalInsertBefore(newChild, refChild, false);
+ } // insertBefore(Node,Node):Node
+
+ /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
+ * to control which mutation events are spawned. This version of the
+ * insertBefore operation allows us to do so. It is not intended
+ * for use by application programs.
+ */
+ Node internalInsertBefore(Node newChild, Node refChild, boolean replace)
+ throws DOMException {
+
+ boolean errorChecking = ownerDocument.errorChecking;
+
+ if (newChild.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
+ // SLOW BUT SAFE: We could insert the whole subtree without
+ // juggling so many next/previous pointers. (Wipe out the
+ // parent's child-list, patch the parent pointers, set the
+ // ends of the list.) But we know some subclasses have special-
+ // case behavior they add to insertBefore(), so we don't risk it.
+ // This approch also takes fewer bytecodes.
+
+ // NOTE: If one of the children is not a legal child of this
+ // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children
+ // have been transferred. (Alternative behaviors would be to
+ // reparent up to the first failure point or reparent all those
+ // which are acceptable to the target node, neither of which is
+ // as robust. PR-DOM-0818 isn't entirely clear on which it
+ // recommends?????
+
+ // No need to check kids for right-document; if they weren't,
+ // they wouldn't be kids of that DocFrag.
+ if (errorChecking) {
+ for (Node kid = newChild.getFirstChild(); // Prescan
+ kid != null; kid = kid.getNextSibling()) {
+
+ if (!ownerDocument.isKidOK(this, kid)) {
+ throw new DOMException(
+ DOMException.HIERARCHY_REQUEST_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null));
+ }
+ }
+ }
+
+ while (newChild.hasChildNodes()) {
+ insertBefore(newChild.getFirstChild(), refChild);
+ }
+ return newChild;
+ }
+
+ if (newChild == refChild) {
+ // stupid case that must be handled as a no-op triggering events...
+ refChild = refChild.getNextSibling();
+ removeChild(newChild);
+ insertBefore(newChild, refChild);
+ return newChild;
+ }
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+
+ if (errorChecking) {
+ if (isReadOnly()) {
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null));
+ }
+ if (newChild.getOwnerDocument() != ownerDocument && newChild != ownerDocument) {
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
+ }
+ if (!ownerDocument.isKidOK(this, newChild)) {
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null));
+ }
+ // refChild must be a child of this node (or null)
+ if (refChild != null && refChild.getParentNode() != this) {
+ throw new DOMException(DOMException.NOT_FOUND_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null));
+ }
+
+ // Prevent cycles in the tree
+ // newChild cannot be ancestor of this Node,
+ // and actually cannot be this
+ boolean treeSafe = true;
+ for (NodeImpl a = this; treeSafe && a != null; a = a.parentNode())
+ {
+ treeSafe = newChild != a;
+ }
+ if(!treeSafe) {
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null));
+ }
+ }
+
+ // notify document
+ ownerDocument.insertingNode(this, replace);
+
+ // Convert to internal type, to avoid repeated casting
+ ChildNode newInternal = (ChildNode)newChild;
+
+ Node oldparent = newInternal.parentNode();
+ if (oldparent != null) {
+ oldparent.removeChild(newInternal);
+ }
+
+ // Convert to internal type, to avoid repeated casting
+ ChildNode refInternal = (ChildNode)refChild;
+
+ // Attach up
+ newInternal.ownerNode = this;
+ newInternal.isOwned(true);
+
+ // Attach before and after
+ // Note: firstChild.previousSibling == lastChild!!
+ if (firstChild == null) {
+ // this our first and only child
+ firstChild = newInternal;
+ newInternal.isFirstChild(true);
+ newInternal.previousSibling = newInternal;
+ }
+ else {
+ if (refInternal == null) {
+ // this is an append
+ ChildNode lastChild = firstChild.previousSibling;
+ lastChild.nextSibling = newInternal;
+ newInternal.previousSibling = lastChild;
+ firstChild.previousSibling = newInternal;
+ }
+ else {
+ // this is an insert
+ if (refChild == firstChild) {
+ // at the head of the list
+ firstChild.isFirstChild(false);
+ newInternal.nextSibling = firstChild;
+ newInternal.previousSibling = firstChild.previousSibling;
+ firstChild.previousSibling = newInternal;
+ firstChild = newInternal;
+ newInternal.isFirstChild(true);
+ }
+ else {
+ // somewhere in the middle
+ ChildNode prev = refInternal.previousSibling;
+ newInternal.nextSibling = refInternal;
+ prev.nextSibling = newInternal;
+ refInternal.previousSibling = newInternal;
+ newInternal.previousSibling = prev;
+ }
+ }
+ }
+
+ changed();
+
+ // update cached length if we have any
+ if (fNodeListCache != null) {
+ if (fNodeListCache.fLength != -1) {
+ fNodeListCache.fLength++;
+ }
+ if (fNodeListCache.fChildIndex != -1) {
+ // if we happen to insert just before the cached node, update
+ // the cache to the new node to match the cached index
+ if (fNodeListCache.fChild == refInternal) {
+ fNodeListCache.fChild = newInternal;
+ } else {
+ // otherwise just invalidate the cache
+ fNodeListCache.fChildIndex = -1;
+ }
+ }
+ }
+
+ // notify document
+ ownerDocument.insertedNode(this, newInternal, replace);
+
+ checkNormalizationAfterInsert(newInternal);
+
+ return newChild;
+
+ } // internalInsertBefore(Node,Node,boolean):Node
+
+ /**
+ * Remove a child from this Node. The removed child's subtree
+ * remains intact so it may be re-inserted elsewhere.
+ *
+ * @return oldChild, in its new state (removed).
+ *
+ * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
+ * this node.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
+ * read-only.
+ */
+ public Node removeChild(Node oldChild)
+ throws DOMException {
+ // Tail-call, should be optimizable
+ return internalRemoveChild(oldChild, false);
+ } // removeChild(Node) :Node
+
+ /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
+ * to control which mutation events are spawned. This version of the
+ * removeChild operation allows us to do so. It is not intended
+ * for use by application programs.
+ */
+ Node internalRemoveChild(Node oldChild, boolean replace)
+ throws DOMException {
+
+ CoreDocumentImpl ownerDocument = ownerDocument();
+ if (ownerDocument.errorChecking) {
+ if (isReadOnly()) {
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null));
+ }
+ if (oldChild != null && oldChild.getParentNode() != this) {
+ throw new DOMException(DOMException.NOT_FOUND_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null));
+ }
+ }
+
+ ChildNode oldInternal = (ChildNode) oldChild;
+
+ // notify document
+ ownerDocument.removingNode(this, oldInternal, replace);
+
+ // Save previous sibling for normalization checking.
+ final ChildNode oldPreviousSibling = oldInternal.previousSibling();
+
+ // update cached length if we have any
+ if (fNodeListCache != null) {
+ if (fNodeListCache.fLength != -1) {
+ fNodeListCache.fLength--;
+ }
+ if (fNodeListCache.fChildIndex != -1) {
+ // if the removed node is the cached node
+ // move the cache to its (soon former) previous sibling
+ if (fNodeListCache.fChild == oldInternal) {
+ fNodeListCache.fChildIndex--;
+ fNodeListCache.fChild = oldPreviousSibling;
+ } else {
+ // otherwise just invalidate the cache
+ fNodeListCache.fChildIndex = -1;
+ }
+ }
+ }
+
+ // Patch linked list around oldChild
+ // Note: lastChild == firstChild.previousSibling
+ if (oldInternal == firstChild) {
+ // removing first child
+ oldInternal.isFirstChild(false);
+ firstChild = oldInternal.nextSibling;
+ if (firstChild != null) {
+ firstChild.isFirstChild(true);
+ firstChild.previousSibling = oldInternal.previousSibling;
+ }
+ } else {
+ ChildNode prev = oldInternal.previousSibling;
+ ChildNode next = oldInternal.nextSibling;
+ prev.nextSibling = next;
+ if (next == null) {
+ // removing last child
+ firstChild.previousSibling = prev;
+ } else {
+ // removing some other child in the middle
+ next.previousSibling = prev;
+ }
+ }
+
+ // Remove oldInternal's references to tree
+ oldInternal.ownerNode = ownerDocument;
+ oldInternal.isOwned(false);
+ oldInternal.nextSibling = null;
+ oldInternal.previousSibling = null;
+
+ changed();
+
+ // notify document
+ ownerDocument.removedNode(this, replace);
+
+ checkNormalizationAfterRemove(oldPreviousSibling);
+
+ return oldInternal;
+
+ } // internalRemoveChild(Node,boolean):Node
+
+ /**
+ * Make newChild occupy the location that oldChild used to
+ * have. Note that newChild will first be removed from its previous
+ * parent, if any. Equivalent to inserting newChild before oldChild,
+ * then removing oldChild.
+ *
+ * @return oldChild, in its new state (removed).
+ *
+ * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
+ * type that shouldn't be a child of this node, or if newChild is
+ * one of our ancestors.
+ *
+ * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
+ * different owner document than we do.
+ *
+ * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
+ * this node.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
+ * read-only.
+ */
+ public Node replaceChild(Node newChild, Node oldChild)
+ throws DOMException {
+ // If Mutation Events are being generated, this operation might
+ // throw aggregate events twice when modifying an Attr -- once
+ // on insertion and once on removal. DOM Level 2 does not specify
+ // this as either desirable or undesirable, but hints that
+ // aggregations should be issued only once per user request.
+
+ // notify document
+ ownerDocument.replacingNode(this);
+
+ internalInsertBefore(newChild, oldChild, true);
+ if (newChild != oldChild) {
+ internalRemoveChild(oldChild, true);
+ }
+
+ // notify document
+ ownerDocument.replacedNode(this);
+
+ return oldChild;
+ }
+
+ /*
+ * Get Node text content
+ * @since DOM Level 3
+ */
+ public String getTextContent() throws DOMException {
+ Node child = getFirstChild();
+ if (child != null) {
+ Node next = child.getNextSibling();
+ if (next == null) {
+ return hasTextContent(child) ? ((NodeImpl) child).getTextContent() : "";
+ }
+ StringBuffer buf = new StringBuffer();
+ getTextContent(buf);
+ return buf.toString();
+ }
+ return "";
+ }
+
+ // internal method taking a StringBuffer in parameter
+ void getTextContent(StringBuffer buf) throws DOMException {
+ Node child = getFirstChild();
+ while (child != null) {
+ if (hasTextContent(child)) {
+ ((NodeImpl) child).getTextContent(buf);
+ }
+ child = child.getNextSibling();
+ }
+ }
+
+ // internal method returning whether to take the given node's text content
+ final boolean hasTextContent(Node child) {
+ return child.getNodeType() != Node.COMMENT_NODE &&
+ child.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE &&
+ (child.getNodeType() != Node.TEXT_NODE ||
+ ((TextImpl) child).isIgnorableWhitespace() == false);
+ }
+
+ /*
+ * Set Node text content
+ * @since DOM Level 3
+ */
+ public void setTextContent(String textContent)
+ throws DOMException {
+ // get rid of any existing children
+ Node child;
+ while ((child = getFirstChild()) != null) {
+ removeChild(child);
+ }
+ // create a Text node to hold the given content
+ if (textContent != null && textContent.length() != 0){
+ appendChild(ownerDocument().createTextNode(textContent));
+ }
+ }
+
+ //
+ // NodeList methods
+ //
+
+ /**
+ * Count the immediate children of this node. Use to implement
+ * NodeList.getLength().
+ * @return int
+ */
+ private int nodeListGetLength() {
+
+ if (fNodeListCache == null) {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ // get rid of trivial cases
+ if (firstChild == null) {
+ return 0;
+ }
+ if (firstChild == lastChild()) {
+ return 1;
+ }
+ // otherwise request a cache object
+ fNodeListCache = ownerDocument.getNodeListCache(this);
+ }
+ if (fNodeListCache.fLength == -1) { // is the cached length invalid ?
+ int l;
+ ChildNode n;
+ // start from the cached node if we have one
+ if (fNodeListCache.fChildIndex != -1 &&
+ fNodeListCache.fChild != null) {
+ l = fNodeListCache.fChildIndex;
+ n = fNodeListCache.fChild;
+ } else {
+ n = firstChild;
+ l = 0;
+ }
+ while (n != null) {
+ l++;
+ n = n.nextSibling;
+ }
+ fNodeListCache.fLength = l;
+ }
+
+ return fNodeListCache.fLength;
+
+ } // nodeListGetLength():int
+
+ /**
+ * NodeList method: Count the immediate children of this node
+ * @return int
+ */
+ public int getLength() {
+ return nodeListGetLength();
+ }
+
+ /**
+ * Return the Nth immediate child of this node, or null if the index is
+ * out of bounds. Use to implement NodeList.item().
+ * @param index int
+ */
+ private Node nodeListItem(int index) {
+
+ if (fNodeListCache == null) {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ // get rid of trivial case
+ if (firstChild == lastChild()) {
+ return index == 0 ? firstChild : null;
+ }
+ // otherwise request a cache object
+ fNodeListCache = ownerDocument.getNodeListCache(this);
+ }
+ int i = fNodeListCache.fChildIndex;
+ ChildNode n = fNodeListCache.fChild;
+ boolean firstAccess = true;
+ // short way
+ if (i != -1 && n != null) {
+ firstAccess = false;
+ if (i < index) {
+ while (i < index && n != null) {
+ i++;
+ n = n.nextSibling;
+ }
+ }
+ else if (i > index) {
+ while (i > index && n != null) {
+ i--;
+ n = n.previousSibling();
+ }
+ }
+ }
+ else {
+ // long way
+ if (index < 0) {
+ return null;
+ }
+ n = firstChild;
+ for (i = 0; i < index && n != null; i++) {
+ n = n.nextSibling;
+ }
+ }
+
+ // release cache if reaching last child or first child
+ if (!firstAccess && (n == firstChild || n == lastChild())) {
+ fNodeListCache.fChildIndex = -1;
+ fNodeListCache.fChild = null;
+ ownerDocument.freeNodeListCache(fNodeListCache);
+ // we can keep using the cache until it is actually reused
+ // fNodeListCache will be nulled by the pool (document) if that
+ // happens.
+ // fNodeListCache = null;
+ }
+ else {
+ // otherwise update it
+ fNodeListCache.fChildIndex = i;
+ fNodeListCache.fChild = n;
+ }
+ return n;
+
+ } // nodeListItem(int):Node
+
+ /**
+ * NodeList method: Return the Nth immediate child of this node, or
+ * null if the index is out of bounds.
+ * @return org.w3c.dom.Node
+ * @param index int
+ */
+ public Node item(int index) {
+ return nodeListItem(index);
+ } // item(int):Node
+
+ /**
+ * Create a NodeList to access children that is use by subclass elements
+ * that have methods named getLength() or item(int). ChildAndParentNode
+ * optimizes getChildNodes() by implementing NodeList itself. However if
+ * a subclass Element implements methods with the same name as the NodeList
+ * methods, they will override the actually methods in this class.
+ *
+ * To use this method, the subclass should implement getChildNodes() and
+ * have it call this method. The resulting NodeList instance maybe
+ * shared and cached in a transient field, but the cached value must be
+ * cleared if the node is cloned.
+ */
+ protected final NodeList getChildNodesUnoptimized() {
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ return new NodeList() {
+ /**
+ * @see NodeList.getLength()
+ */
+ public int getLength() {
+ return nodeListGetLength();
+ } // getLength():int
+
+ /**
+ * @see NodeList.item(int)
+ */
+ public Node item(int index) {
+ return nodeListItem(index);
+ } // item(int):Node
+ };
+ } // getChildNodesUnoptimized():NodeList
+
+ //
+ // DOM2: methods, getters, setters
+ //
+
+ /**
+ * Override default behavior to call normalize() on this Node's
+ * children. It is up to implementors or Node to override normalize()
+ * to take action.
+ */
+ public void normalize() {
+ // No need to normalize if already normalized.
+ if (isNormalized()) {
+ return;
+ }
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ ChildNode kid;
+ for (kid = firstChild; kid != null; kid = kid.nextSibling) {
+ kid.normalize();
+ }
+ isNormalized(true);
+ }
+
+ /**
+ * DOM Level 3 WD- Experimental.
+ * Override inherited behavior from NodeImpl to support deep equal.
+ */
+ public boolean isEqualNode(Node arg) {
+ if (!super.isEqualNode(arg)) {
+ return false;
+ }
+ // there are many ways to do this test, and there isn't any way
+ // better than another. Performance may vary greatly depending on
+ // the implementations involved. This one should work fine for us.
+ Node child1 = getFirstChild();
+ Node child2 = arg.getFirstChild();
+ while (child1 != null && child2 != null) {
+ if (!child1.isEqualNode(child2)) {
+ return false;
+ }
+ child1 = child1.getNextSibling();
+ child2 = child2.getNextSibling();
+ }
+ if (child1 != child2) {
+ return false;
+ }
+ return true;
+ }
+
+ //
+ // Public methods
+ //
+
+ /**
+ * Override default behavior so that if deep is true, children are also
+ * toggled.
+ * @see Node
+ *
+ * Note: this will not change the state of an EntityReference or its
+ * children, which are always read-only.
+ */
+ public void setReadOnly(boolean readOnly, boolean deep) {
+
+ super.setReadOnly(readOnly, deep);
+
+ if (deep) {
+
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+
+ // Recursively set kids
+ for (ChildNode mykid = firstChild;
+ mykid != null;
+ mykid = mykid.nextSibling) {
+ if (mykid.getNodeType() != Node.ENTITY_REFERENCE_NODE) {
+ mykid.setReadOnly(readOnly,true);
+ }
+ }
+ }
+ } // setReadOnly(boolean,boolean)
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * Override this method in subclass to hook in efficient
+ * internal data structure.
+ */
+ protected void synchronizeChildren() {
+ // By default just change the flag to avoid calling this method again
+ needsSyncChildren(false);
+ }
+
+ /**
+ * Checks the normalized state of this node after inserting a child.
+ * If the inserted child causes this node to be unnormalized, then this
+ * node is flagged accordingly.
+ * The conditions for changing the normalized state are:
+ *
+ * - The inserted child is a text node and one of its adjacent siblings
+ * is also a text node.
+ *
- The inserted child is is itself unnormalized.
+ *
+ *
+ * @param insertedChild the child node that was inserted into this node
+ *
+ * @throws NullPointerException if the inserted child is null
+ */
+ void checkNormalizationAfterInsert(ChildNode insertedChild) {
+ // See if insertion caused this node to be unnormalized.
+ if (insertedChild.getNodeType() == Node.TEXT_NODE) {
+ ChildNode prev = insertedChild.previousSibling();
+ ChildNode next = insertedChild.nextSibling;
+ // If an adjacent sibling of the new child is a text node,
+ // flag this node as unnormalized.
+ if ((prev != null && prev.getNodeType() == Node.TEXT_NODE) ||
+ (next != null && next.getNodeType() == Node.TEXT_NODE)) {
+ isNormalized(false);
+ }
+ }
+ else {
+ // If the new child is not normalized,
+ // then this node is inherently not normalized.
+ if (!insertedChild.isNormalized()) {
+ isNormalized(false);
+ }
+ }
+ } // checkNormalizationAfterInsert(ChildNode)
+
+ /**
+ * Checks the normalized of this node after removing a child.
+ * If the removed child causes this node to be unnormalized, then this
+ * node is flagged accordingly.
+ * The conditions for changing the normalized state are:
+ *
+ * - The removed child had two adjacent siblings that were text nodes.
+ *
+ *
+ * @param previousSibling the previous sibling of the removed child, or
+ * null
+ */
+ void checkNormalizationAfterRemove(ChildNode previousSibling) {
+ // See if removal caused this node to be unnormalized.
+ // If the adjacent siblings of the removed child were both text nodes,
+ // flag this node as unnormalized.
+ if (previousSibling != null &&
+ previousSibling.getNodeType() == Node.TEXT_NODE) {
+
+ ChildNode next = previousSibling.nextSibling;
+ if (next != null && next.getNodeType() == Node.TEXT_NODE) {
+ isNormalized(false);
+ }
+ }
+ } // checkNormalizationAfterRemove(Node)
+
+ //
+ // Serialization methods
+ //
+
+ /** Serialize object. */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+
+ // synchronize children
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ // write object
+ out.defaultWriteObject();
+
+ } // writeObject(ObjectOutputStream)
+
+ /** Deserialize object. */
+ private void readObject(ObjectInputStream ois)
+ throws ClassNotFoundException, IOException {
+
+ // perform default deseralization
+ ois.defaultReadObject();
+
+ // hardset synchildren - so we don't try to sync - it does not make any
+ // sense to try to synchildren when we just deserialize object.
+ needsSyncChildren(false);
+
+ } // readObject(ObjectInputStream)
+
+ /*
+ * a class to store some user data along with its handler
+ */
+ class UserDataRecord implements Serializable {
+ /** Serialization version. */
+ private static final long serialVersionUID = 3258126977134310455L;
+
+ Object fData;
+ UserDataHandler fHandler;
+ UserDataRecord(Object data, UserDataHandler handler) {
+ fData = data;
+ fHandler = handler;
+ }
+ }
+} // class ParentNode
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/ProcessingInstructionImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/ProcessingInstructionImpl.java
new file mode 100644
index 0000000..bbe5ecb
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/ProcessingInstructionImpl.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+
+/**
+ * Processing Instructions (PIs) permit documents to carry
+ * processor-specific information alongside their actual content. PIs
+ * are most common in XML, but they are supported in HTML as well.
+ *
+ * This class inherits from CharacterDataImpl to reuse its setNodeValue method.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class ProcessingInstructionImpl
+ extends CharacterDataImpl
+ implements ProcessingInstruction {
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = 7554435174099981510L;
+
+ //
+ // Data
+ //
+
+ protected String target;
+
+ //
+ // Constructors
+ //
+
+ /** Factory constructor. */
+ public ProcessingInstructionImpl(CoreDocumentImpl ownerDoc,
+ String target, String data) {
+ super(ownerDoc, data);
+ this.target = target;
+ }
+
+ //
+ // Node methods
+ //
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public short getNodeType() {
+ return Node.PROCESSING_INSTRUCTION_NODE;
+ }
+
+ /**
+ * Returns the target
+ */
+ public String getNodeName() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return target;
+ }
+
+ //
+ // ProcessingInstruction methods
+ //
+
+ /**
+ * A PI's "target" states what processor channel the PI's data
+ * should be directed to. It is defined differently in HTML and XML.
+ *
+ * In XML, a PI's "target" is the first (whitespace-delimited) token
+ * following the "" token that begins the PI.
+ *
+ * In HTML, target is always null.
+ *
+ * Note that getNodeName is aliased to getTarget.
+ */
+ public String getTarget() {
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return target;
+
+ } // getTarget():String
+
+ /**
+ * Returns the absolute base URI of this node or null if the implementation
+ * wasn't able to obtain an absolute URI. Note: If the URI is malformed, a
+ * null is returned.
+ *
+ * @return The absolute base URI of this node or null.
+ * @since DOM Level 3
+ */
+ public String getBaseURI() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return ownerNode.getBaseURI();
+ }
+
+
+} // class ProcessingInstructionImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/RangeExceptionImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/RangeExceptionImpl.java
new file mode 100644
index 0000000..f9a2316
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/RangeExceptionImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.xerces.dom;
+
+import org.w3c.dom.ranges.RangeException;
+
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+
+public class RangeExceptionImpl extends RangeException {
+
+ /** Serialization version. */
+ static final long serialVersionUID = -9058052627467240856L;
+
+ public RangeExceptionImpl(short code, String message) {
+ super(code,message);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/RangeImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/RangeImpl.java
new file mode 100644
index 0000000..a05bfdd
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/RangeImpl.java
@@ -0,0 +1,2099 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.util.ArrayList;
+
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Node;
+import org.w3c.dom.ranges.Range;
+import org.w3c.dom.ranges.RangeException;
+
+/**
+ * The RangeImpl class implements the org.w3c.dom.range.Range interface.
+ * Please see the API documentation for the interface classes
+ * and use the interfaces in your client programs.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class RangeImpl implements Range {
+
+ //
+ // Constants
+ //
+
+
+ //
+ // Data
+ //
+
+ private DocumentImpl fDocument;
+ private Node fStartContainer;
+ private Node fEndContainer;
+ private int fStartOffset;
+ private int fEndOffset;
+ private boolean fDetach = false;
+ private Node fInsertNode = null;
+ private Node fDeleteNode = null;
+ private Node fSplitNode = null;
+ // Was the Node inserted from the Range or the Document
+ private boolean fInsertedFromRange = false;
+
+ /** The constructor. Clients must use DocumentRange.createRange(),
+ * because it registers the Range with the document, so it can
+ * be fixed-up.
+ */
+ public RangeImpl(DocumentImpl document) {
+ fDocument = document;
+ fStartContainer = document;
+ fEndContainer = document;
+ fStartOffset = 0;
+ fEndOffset = 0;
+ fDetach = false;
+ }
+
+ public Node getStartContainer() {
+ if ( fDetach ) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ return fStartContainer;
+ }
+
+ public int getStartOffset() {
+ if ( fDetach ) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ return fStartOffset;
+ }
+
+ public Node getEndContainer() {
+ if ( fDetach ) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ return fEndContainer;
+ }
+
+ public int getEndOffset() {
+ if ( fDetach ) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ return fEndOffset;
+ }
+
+ public boolean getCollapsed() {
+ if ( fDetach ) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ return (fStartContainer == fEndContainer
+ && fStartOffset == fEndOffset);
+ }
+
+ public Node getCommonAncestorContainer() {
+ if ( fDetach ) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ ArrayList startV = new ArrayList();
+ Node node;
+ for (node=fStartContainer; node != null;
+ node=node.getParentNode())
+ {
+ startV.add(node);
+ }
+ ArrayList endV = new ArrayList();
+ for (node=fEndContainer; node != null;
+ node=node.getParentNode())
+ {
+ endV.add(node);
+ }
+ int s = startV.size()-1;
+ int e = endV.size()-1;
+ Object result = null;
+ while (s>=0 && e>=0) {
+ if (startV.get(s) == endV.get(e)) {
+ result = startV.get(s);
+ } else {
+ break;
+ }
+ --s;
+ --e;
+ }
+ return (Node)result;
+ }
+
+
+ public void setStart(Node refNode, int offset)
+ throws RangeException, DOMException
+ {
+ if (fDocument.errorChecking) {
+ if ( fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ if ( !isLegalContainer(refNode)) {
+ throw new RangeExceptionImpl(
+ RangeException.INVALID_NODE_TYPE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
+ }
+ if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
+ throw new DOMException(
+ DOMException.WRONG_DOCUMENT_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
+ }
+ }
+
+ checkIndex(refNode, offset);
+
+ fStartContainer = refNode;
+ fStartOffset = offset;
+
+ // If one boundary-point of a Range is set to have a root container
+ // other
+ // than the current one for the Range, the Range should be collapsed to
+ // the new position.
+ // The start position of a Range should never be after the end position.
+ if (getCommonAncestorContainer() == null
+ || (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) {
+ collapse(true);
+ }
+ }
+
+ public void setEnd(Node refNode, int offset)
+ throws RangeException, DOMException
+ {
+ if (fDocument.errorChecking) {
+ if (fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ if ( !isLegalContainer(refNode)) {
+ throw new RangeExceptionImpl(
+ RangeException.INVALID_NODE_TYPE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
+ }
+ if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
+ throw new DOMException(
+ DOMException.WRONG_DOCUMENT_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
+ }
+ }
+
+ checkIndex(refNode, offset);
+
+ fEndContainer = refNode;
+ fEndOffset = offset;
+
+ // If one boundary-point of a Range is set to have a root container
+ // other
+ // than the current one for the Range, the Range should be collapsed to
+ // the new position.
+ // The start position of a Range should never be after the end position.
+ if (getCommonAncestorContainer() == null
+ || (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) {
+ collapse(false);
+ }
+ }
+
+ public void setStartBefore(Node refNode)
+ throws RangeException
+ {
+ if (fDocument.errorChecking) {
+ if (fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ if ( !hasLegalRootContainer(refNode) ||
+ !isLegalContainedNode(refNode) )
+ {
+ throw new RangeExceptionImpl(
+ RangeException.INVALID_NODE_TYPE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
+ }
+ if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
+ throw new DOMException(
+ DOMException.WRONG_DOCUMENT_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
+ }
+ }
+
+ fStartContainer = refNode.getParentNode();
+ int i = 0;
+ for (Node n = refNode; n!=null; n = n.getPreviousSibling()) {
+ i++;
+ }
+ fStartOffset = i-1;
+
+ // If one boundary-point of a Range is set to have a root container
+ // other
+ // than the current one for the Range, the Range should be collapsed to
+ // the new position.
+ // The start position of a Range should never be after the end position.
+ if (getCommonAncestorContainer() == null
+ || (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) {
+ collapse(true);
+ }
+ }
+
+ public void setStartAfter(Node refNode)
+ throws RangeException
+ {
+ if (fDocument.errorChecking) {
+ if (fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ if ( !hasLegalRootContainer(refNode) ||
+ !isLegalContainedNode(refNode)) {
+ throw new RangeExceptionImpl(
+ RangeException.INVALID_NODE_TYPE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
+ }
+ if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
+ throw new DOMException(
+ DOMException.WRONG_DOCUMENT_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
+ }
+ }
+ fStartContainer = refNode.getParentNode();
+ int i = 0;
+ for (Node n = refNode; n!=null; n = n.getPreviousSibling()) {
+ i++;
+ }
+ fStartOffset = i;
+
+ // If one boundary-point of a Range is set to have a root container
+ // other
+ // than the current one for the Range, the Range should be collapsed to
+ // the new position.
+ // The start position of a Range should never be after the end position.
+ if (getCommonAncestorContainer() == null
+ || (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) {
+ collapse(true);
+ }
+ }
+
+ public void setEndBefore(Node refNode)
+ throws RangeException
+ {
+ if (fDocument.errorChecking) {
+ if (fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ if ( !hasLegalRootContainer(refNode) ||
+ !isLegalContainedNode(refNode)) {
+ throw new RangeExceptionImpl(
+ RangeException.INVALID_NODE_TYPE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
+ }
+ if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
+ throw new DOMException(
+ DOMException.WRONG_DOCUMENT_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
+ }
+ }
+ fEndContainer = refNode.getParentNode();
+ int i = 0;
+ for (Node n = refNode; n!=null; n = n.getPreviousSibling()) {
+ i++;
+ }
+ fEndOffset = i-1;
+
+ // If one boundary-point of a Range is set to have a root container
+ // other
+ // than the current one for the Range, the Range should be collapsed to
+ // the new position.
+ // The start position of a Range should never be after the end position.
+ if (getCommonAncestorContainer() == null
+ || (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) {
+ collapse(false);
+ }
+ }
+
+ public void setEndAfter(Node refNode)
+ throws RangeException
+ {
+ if (fDocument.errorChecking) {
+ if( fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ if ( !hasLegalRootContainer(refNode) ||
+ !isLegalContainedNode(refNode)) {
+ throw new RangeExceptionImpl(
+ RangeException.INVALID_NODE_TYPE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
+ }
+ if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
+ throw new DOMException(
+ DOMException.WRONG_DOCUMENT_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
+ }
+ }
+ fEndContainer = refNode.getParentNode();
+ int i = 0;
+ for (Node n = refNode; n!=null; n = n.getPreviousSibling()) {
+ i++;
+ }
+ fEndOffset = i;
+
+ // If one boundary-point of a Range is set to have a root container
+ // other
+ // than the current one for the Range, the Range should be collapsed to
+ // the new position.
+ // The start position of a Range should never be after the end position.
+ if (getCommonAncestorContainer() == null
+ || (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) {
+ collapse(false);
+ }
+ }
+
+ public void collapse(boolean toStart) {
+
+ if( fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+
+ if (toStart) {
+ fEndContainer = fStartContainer;
+ fEndOffset = fStartOffset;
+ } else {
+ fStartContainer = fEndContainer;
+ fStartOffset = fEndOffset;
+ }
+ }
+
+ public void selectNode(Node refNode)
+ throws RangeException
+ {
+ if (fDocument.errorChecking) {
+ if (fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ if ( !isLegalContainer( refNode.getParentNode() ) ||
+ !isLegalContainedNode( refNode ) ) {
+ throw new RangeExceptionImpl(
+ RangeException.INVALID_NODE_TYPE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
+ }
+ if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
+ throw new DOMException(
+ DOMException.WRONG_DOCUMENT_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
+ }
+ }
+ Node parent = refNode.getParentNode();
+ if (parent != null ) // REVIST: what to do if it IS null?
+ {
+ fStartContainer = parent;
+ fEndContainer = parent;
+ int i = 0;
+ for (Node n = refNode; n!=null; n = n.getPreviousSibling()) {
+ i++;
+ }
+ fStartOffset = i-1;
+ fEndOffset = fStartOffset+1;
+ }
+ }
+
+ public void selectNodeContents(Node refNode)
+ throws RangeException
+ {
+ if (fDocument.errorChecking) {
+ if( fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ if ( !isLegalContainer(refNode)) {
+ throw new RangeExceptionImpl(
+ RangeException.INVALID_NODE_TYPE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
+ }
+ if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
+ throw new DOMException(
+ DOMException.WRONG_DOCUMENT_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
+ }
+ }
+ fStartContainer = refNode;
+ fEndContainer = refNode;
+ Node first = refNode.getFirstChild();
+ fStartOffset = 0;
+ if (first == null) {
+ fEndOffset = 0;
+ } else {
+ int i = 0;
+ for (Node n = first; n!=null; n = n.getNextSibling()) {
+ i++;
+ }
+ fEndOffset = i;
+ }
+
+ }
+
+ public short compareBoundaryPoints(short how, Range sourceRange)
+ throws DOMException
+ {
+ if (fDocument.errorChecking) {
+ if( fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ // WRONG_DOCUMENT_ERR: Raised if the two Ranges are not in the same Document or DocumentFragment.
+ if ((fDocument != sourceRange.getStartContainer().getOwnerDocument()
+ && fDocument != sourceRange.getStartContainer()
+ && sourceRange.getStartContainer() != null)
+ || (fDocument != sourceRange.getEndContainer().getOwnerDocument()
+ && fDocument != sourceRange.getEndContainer()
+ && sourceRange.getStartContainer() != null)) {
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
+ DOMMessageFormatter.formatMessage( DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
+ }
+ }
+
+ Node endPointA;
+ Node endPointB;
+ int offsetA;
+ int offsetB;
+
+ if (how == START_TO_START) {
+ endPointA = sourceRange.getStartContainer();
+ endPointB = fStartContainer;
+ offsetA = sourceRange.getStartOffset();
+ offsetB = fStartOffset;
+ } else
+ if (how == START_TO_END) {
+ endPointA = sourceRange.getStartContainer();
+ endPointB = fEndContainer;
+ offsetA = sourceRange.getStartOffset();
+ offsetB = fEndOffset;
+ } else
+ if (how == END_TO_START) {
+ endPointA = sourceRange.getEndContainer();
+ endPointB = fStartContainer;
+ offsetA = sourceRange.getEndOffset();
+ offsetB = fStartOffset;
+ } else {
+ endPointA = sourceRange.getEndContainer();
+ endPointB = fEndContainer;
+ offsetA = sourceRange.getEndOffset();
+ offsetB = fEndOffset;
+ }
+
+ // The DOM Spec outlines four cases that need to be tested
+ // to compare two range boundary points:
+ // case 1: same container
+ // case 2: Child C of container A is ancestor of B
+ // case 3: Child C of container B is ancestor of A
+ // case 4: preorder traversal of context tree.
+
+ // case 1: same container
+ if (endPointA == endPointB) {
+ if (offsetA < offsetB) return 1;
+ if (offsetA == offsetB) return 0;
+ return -1;
+ }
+ // case 2: Child C of container A is ancestor of B
+ // This can be quickly tested by walking the parent chain of B
+ for ( Node c = endPointB, p = c.getParentNode();
+ p != null;
+ c = p, p = p.getParentNode())
+ {
+ if (p == endPointA) {
+ int index = indexOf(c, endPointA);
+ if (offsetA <= index) return 1;
+ return -1;
+ }
+ }
+
+ // case 3: Child C of container B is ancestor of A
+ // This can be quickly tested by walking the parent chain of A
+ for ( Node c = endPointA, p = c.getParentNode();
+ p != null;
+ c = p, p = p.getParentNode())
+ {
+ if (p == endPointB) {
+ int index = indexOf(c, endPointB);
+ if (index < offsetB) return 1;
+ return -1;
+ }
+ }
+
+ // case 4: preorder traversal of context tree.
+ // Instead of literally walking the context tree in pre-order,
+ // we use relative node depth walking which is usually faster
+
+ int depthDiff = 0;
+ for ( Node n = endPointA; n != null; n = n.getParentNode() )
+ depthDiff++;
+ for ( Node n = endPointB; n != null; n = n.getParentNode() )
+ depthDiff--;
+ while (depthDiff > 0) {
+ endPointA = endPointA.getParentNode();
+ depthDiff--;
+ }
+ while (depthDiff < 0) {
+ endPointB = endPointB.getParentNode();
+ depthDiff++;
+ }
+ for (Node pA = endPointA.getParentNode(),
+ pB = endPointB.getParentNode();
+ pA != pB;
+ pA = pA.getParentNode(), pB = pB.getParentNode() )
+ {
+ endPointA = pA;
+ endPointB = pB;
+ }
+ for ( Node n = endPointA.getNextSibling();
+ n != null;
+ n = n.getNextSibling() )
+ {
+ if (n == endPointB) {
+ return 1;
+ }
+ }
+ return -1;
+ }
+
+ public void deleteContents()
+ throws DOMException
+ {
+ traverseContents(DELETE_CONTENTS);
+ }
+
+ public DocumentFragment extractContents()
+ throws DOMException
+ {
+ return traverseContents(EXTRACT_CONTENTS);
+ }
+
+ public DocumentFragment cloneContents()
+ throws DOMException
+ {
+ return traverseContents(CLONE_CONTENTS);
+ }
+
+ public void insertNode(Node newNode)
+ throws DOMException, RangeException
+ {
+ if ( newNode == null ) return; //throw exception?
+
+ int type = newNode.getNodeType();
+
+ if (fDocument.errorChecking) {
+ if (fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ if ( fDocument != newNode.getOwnerDocument() ) {
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
+ }
+
+ if (type == Node.ATTRIBUTE_NODE
+ || type == Node.ENTITY_NODE
+ || type == Node.NOTATION_NODE
+ || type == Node.DOCUMENT_NODE)
+ {
+ throw new RangeExceptionImpl(
+ RangeException.INVALID_NODE_TYPE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
+ }
+ }
+ Node cloneCurrent;
+ Node current;
+ int currentChildren = 0;
+ fInsertedFromRange = true;
+
+ //boolean MULTIPLE_MODE = false;
+ if (fStartContainer.getNodeType() == Node.TEXT_NODE) {
+
+ Node parent = fStartContainer.getParentNode();
+ currentChildren = parent.getChildNodes().getLength(); //holds number of kids before insertion
+ // split text node: results is 3 nodes..
+ cloneCurrent = fStartContainer.cloneNode(false);
+ ((TextImpl)cloneCurrent).setNodeValueInternal(
+ (cloneCurrent.getNodeValue()).substring(fStartOffset));
+ ((TextImpl)fStartContainer).setNodeValueInternal(
+ (fStartContainer.getNodeValue()).substring(0,fStartOffset));
+ Node next = fStartContainer.getNextSibling();
+ if (next != null) {
+ if (parent != null) {
+ parent.insertBefore(newNode, next);
+ parent.insertBefore(cloneCurrent, next);
+ }
+ } else {
+ if (parent != null) {
+ parent.appendChild(newNode);
+ parent.appendChild(cloneCurrent);
+ }
+ }
+ //update ranges after the insertion
+ if ( fEndContainer == fStartContainer) {
+ fEndContainer = cloneCurrent; //endContainer is the new Node created
+ fEndOffset -= fStartOffset;
+ }
+ else if ( fEndContainer == parent ) { //endContainer was not a text Node.
+ //endOffset + = number_of_children_added
+ fEndOffset += (parent.getChildNodes().getLength() - currentChildren);
+ }
+
+ // signal other Ranges to update their start/end containers/offsets
+ signalSplitData(fStartContainer, cloneCurrent, fStartOffset);
+
+
+ } else { // ! TEXT_NODE
+ if ( fEndContainer == fStartContainer ) //need to remember number of kids
+ currentChildren= fEndContainer.getChildNodes().getLength();
+
+ current = fStartContainer.getFirstChild();
+ int i = 0;
+ for(i = 0; i < fStartOffset && current != null; i++) {
+ current=current.getNextSibling();
+ }
+ if (current != null) {
+ fStartContainer.insertBefore(newNode, current);
+ } else {
+ fStartContainer.appendChild(newNode);
+ }
+ //update fEndOffset. ex: . Range(start;end): body,0; body,1
+ // insert : . Range(start;end): body,0; body,2
+ if ( fEndContainer == fStartContainer && fEndOffset != 0 ) { //update fEndOffset if not 0
+ fEndOffset += (fEndContainer.getChildNodes().getLength() - currentChildren);
+ }
+ }
+ fInsertedFromRange = false;
+ }
+
+ public void surroundContents(Node newParent)
+ throws DOMException, RangeException
+ {
+ if (newParent==null) return;
+ int type = newParent.getNodeType();
+
+ if (fDocument.errorChecking) {
+ if (fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ if (type == Node.ATTRIBUTE_NODE
+ || type == Node.ENTITY_NODE
+ || type == Node.NOTATION_NODE
+ || type == Node.DOCUMENT_TYPE_NODE
+ || type == Node.DOCUMENT_NODE
+ || type == Node.DOCUMENT_FRAGMENT_NODE)
+ {
+ throw new RangeExceptionImpl(
+ RangeException.INVALID_NODE_TYPE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
+ }
+ }
+
+ Node realStart = fStartContainer;
+ Node realEnd = fEndContainer;
+ if (fStartContainer.getNodeType() == Node.TEXT_NODE) {
+ realStart = fStartContainer.getParentNode();
+ }
+ if (fEndContainer.getNodeType() == Node.TEXT_NODE) {
+ realEnd = fEndContainer.getParentNode();
+ }
+
+ if (realStart != realEnd) {
+ throw new RangeExceptionImpl(
+ RangeException.BAD_BOUNDARYPOINTS_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "BAD_BOUNDARYPOINTS_ERR", null));
+ }
+
+ DocumentFragment frag = extractContents();
+ insertNode(newParent);
+ newParent.appendChild(frag);
+ selectNode(newParent);
+ }
+
+ public Range cloneRange(){
+ if( fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+
+ Range range = fDocument.createRange();
+ range.setStart(fStartContainer, fStartOffset);
+ range.setEnd(fEndContainer, fEndOffset);
+ return range;
+ }
+
+ public String toString(){
+ if( fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+
+ Node node = fStartContainer;
+ Node stopNode = fEndContainer;
+ StringBuffer sb = new StringBuffer();
+ if (fStartContainer.getNodeType() == Node.TEXT_NODE
+ || fStartContainer.getNodeType() == Node.CDATA_SECTION_NODE
+ ) {
+ if (fStartContainer == fEndContainer) {
+ sb.append(fStartContainer.getNodeValue().substring(fStartOffset, fEndOffset));
+ return sb.toString();
+ }
+ sb.append(fStartContainer.getNodeValue().substring(fStartOffset));
+ node=nextNode (node,true); //fEndContainer!=fStartContainer
+
+ }
+ else { //fStartContainer is not a TextNode
+ node=node.getFirstChild();
+ if (fStartOffset>0) { //find a first node within a range, specified by fStartOffset
+ int counter=0;
+ while (counter0 && stopNode!=null ){
+ --i;
+ stopNode = stopNode.getNextSibling();
+ }
+ if ( stopNode == null )
+ stopNode = nextNode( fEndContainer, false );
+ }
+ while (node != stopNode) { //look into all kids of the Range
+ if (node == null) break;
+ if (node.getNodeType() == Node.TEXT_NODE
+ || node.getNodeType() == Node.CDATA_SECTION_NODE) {
+ sb.append(node.getNodeValue());
+ }
+
+ node = nextNode(node, true);
+ }
+
+ if (fEndContainer.getNodeType() == Node.TEXT_NODE
+ || fEndContainer.getNodeType() == Node.CDATA_SECTION_NODE) {
+ sb.append(fEndContainer.getNodeValue().substring(0,fEndOffset));
+ }
+ return sb.toString();
+ }
+
+ public void detach() {
+ if( fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+ fDetach = true;
+ fDocument.removeRange(this);
+ }
+
+ //
+ // Mutation functions
+ //
+
+ /** Signal other Ranges to update their start/end
+ * containers/offsets. The data has already been split
+ * into the two Nodes.
+ */
+ void signalSplitData(Node node, Node newNode, int offset) {
+ fSplitNode = node;
+ // notify document
+ fDocument.splitData(node, newNode, offset);
+ fSplitNode = null;
+ }
+
+ /** Fix up this Range if another Range has split a Text Node
+ * into 2 Nodes.
+ */
+ void receiveSplitData(Node node, Node newNode, int offset) {
+ if (node == null || newNode == null) return;
+ if (fSplitNode == node) return;
+
+ if (node == fStartContainer
+ && fStartContainer.getNodeType() == Node.TEXT_NODE) {
+ if (fStartOffset > offset) {
+ fStartOffset = fStartOffset - offset;
+ fStartContainer = newNode;
+ }
+ }
+ if (node == fEndContainer
+ && fEndContainer.getNodeType() == Node.TEXT_NODE) {
+ if (fEndOffset > offset) {
+ fEndOffset = fEndOffset-offset;
+ fEndContainer = newNode;
+ }
+ }
+
+ }
+
+ /** This function inserts text into a Node and invokes
+ * a method to fix-up all other Ranges.
+ */
+ void deleteData(CharacterData node, int offset, int count) {
+ fDeleteNode = node;
+ node.deleteData( offset, count);
+ fDeleteNode = null;
+ }
+
+
+ /** This function is called from DOM.
+ * The text has already beeen inserted.
+ * Fix-up any offsets.
+ */
+ void receiveDeletedText(CharacterDataImpl node, int offset, int count) {
+ if (node == null) return;
+ if (fDeleteNode == node) return;
+ if (node == fStartContainer) {
+ if (fStartOffset > offset + count) {
+ fStartOffset = offset + (fStartOffset - (offset + count));
+ }
+ else if (fStartOffset > offset) {
+ fStartOffset = offset;
+ }
+ }
+ if (node == fEndContainer) {
+ if (fEndOffset > offset + count) {
+ fEndOffset = offset + (fEndOffset - (offset + count));
+ }
+ else if (fEndOffset > offset) {
+ fEndOffset = offset;
+ }
+ }
+
+ }
+
+ /** This function inserts text into a Node and invokes
+ * a method to fix-up all other Ranges.
+ */
+ void insertData(CharacterData node, int index, String insert) {
+ fInsertNode = node;
+ node.insertData( index, insert);
+ fInsertNode = null;
+ }
+
+
+ /**
+ * This function is called from DOM.
+ * The text has already beeen inserted.
+ * Fix-up any offsets.
+ */
+ void receiveInsertedText(CharacterDataImpl node, int index, int len) {
+ if (node == null) return;
+ if (fInsertNode == node) return;
+ if (node == fStartContainer) {
+ if (index < fStartOffset) {
+ fStartOffset = fStartOffset + len;
+ }
+ }
+ if (node == fEndContainer) {
+ if (index < fEndOffset) {
+ fEndOffset = fEndOffset + len;
+ }
+ }
+ }
+
+ /**
+ * This function is called from DOM.
+ * The text has already beeen replaced.
+ * Fix-up any offsets.
+ */
+ void receiveReplacedText(CharacterDataImpl node) {
+ if (node == null) return;
+ if (node == fStartContainer) {
+ fStartOffset = 0;
+ }
+ if (node == fEndContainer) {
+ fEndOffset = 0;
+ }
+ }
+
+ /** This function is called from the DOM.
+ * This node has already been inserted into the DOM.
+ * Fix-up any offsets.
+ */
+ public void insertedNodeFromDOM(Node node) {
+ if (node == null) return;
+ if (fInsertNode == node) return;
+ if (fInsertedFromRange) return; // Offsets are adjusted in Range.insertNode
+
+ Node parent = node.getParentNode();
+
+ if (parent == fStartContainer) {
+ int index = indexOf(node, fStartContainer);
+ if (index < fStartOffset) {
+ fStartOffset++;
+ }
+ }
+
+ if (parent == fEndContainer) {
+ int index = indexOf(node, fEndContainer);
+ if (index < fEndOffset) {
+ fEndOffset++;
+ }
+ }
+
+ }
+
+ /** This function is called within Range
+ * instead of Node.removeChild,
+ * so that the range can remember that it is actively
+ * removing this child.
+ */
+
+ private Node fRemoveChild = null;
+ Node removeChild(Node parent, Node child) {
+ fRemoveChild = child;
+ Node n = parent.removeChild(child);
+ fRemoveChild = null;
+ return n;
+ }
+
+ /** This function must be called by the DOM _BEFORE_
+ * a node is deleted, because at that time it is
+ * connected in the DOM tree, which we depend on.
+ */
+ void removeNode(Node node) {
+ if (node == null) return;
+ if (fRemoveChild == node) return;
+
+ Node parent = node.getParentNode();
+
+ if (parent == fStartContainer) {
+ int index = indexOf(node, fStartContainer);
+ if (index < fStartOffset) {
+ fStartOffset--;
+ }
+ }
+
+ if (parent == fEndContainer) {
+ int index = indexOf(node, fEndContainer);
+ if (index < fEndOffset) {
+ fEndOffset--;
+ }
+ }
+ //startContainer or endContainer or both is/are the ancestor(s) of the Node to be deleted
+ if (parent != fStartContainer
+ || parent != fEndContainer) {
+ if (isAncestorOf(node, fStartContainer)) {
+ fStartContainer = parent;
+ fStartOffset = indexOf( node, parent);
+ }
+ if (isAncestorOf(node, fEndContainer)) {
+ fEndContainer = parent;
+ fEndOffset = indexOf( node, parent);
+ }
+ }
+
+ }
+
+ //
+ // Utility functions.
+ //
+
+ // parameters for traverseContents(int)
+ //REVIST: use boolean, since there are only 2 now...
+ static final int EXTRACT_CONTENTS = 1;
+ static final int CLONE_CONTENTS = 2;
+ static final int DELETE_CONTENTS = 3;
+
+ /**
+ * This is the master routine invoked to visit the nodes
+ * selected by this range. For each such node, different
+ * actions are taken depending on the value of the
+ * how argument.
+ *
+ * @param how Specifies what type of traversal is being
+ * requested (extract, clone, or delete).
+ * Legal values for this argument are:
+ *
+ *
+ * EXTRACT_CONTENTS - will produce
+ * a document fragment containing the range's content.
+ * Partially selected nodes are copied, but fully
+ * selected nodes are moved.
+ *
+ * CLONE_CONTENTS - will leave the
+ * context tree of the range undisturbed, but sill
+ * produced cloned content in a document fragment
+ *
+ * DELETE_CONTENTS - will delete from
+ * the context tree of the range, all fully selected
+ * nodes.
+ *
+ *
+ * @return Returns a document fragment containing any
+ * copied or extracted nodes. If the how
+ * parameter was DELETE_CONTENTS , the
+ * return value is null.
+ */
+ private DocumentFragment traverseContents( int how )
+ throws DOMException
+ {
+ if (fStartContainer == null || fEndContainer == null) {
+ return null; // REVIST: Throw exception?
+ }
+
+ //Check for a detached range.
+ if( fDetach) {
+ throw new DOMException(
+ DOMException.INVALID_STATE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
+ }
+
+ /*
+ Traversal is accomplished by first determining the
+ relationship between the endpoints of the range.
+ For each of four significant relationships, we will
+ delegate the traversal call to a method that
+ can make appropriate assumptions.
+ */
+
+ // case 1: same container
+ if ( fStartContainer == fEndContainer )
+ return traverseSameContainer( how );
+
+
+ // case 2: Child C of start container is ancestor of end container
+ // This can be quickly tested by walking the parent chain of
+ // end container
+ int endContainerDepth = 0;
+ for ( Node c = fEndContainer, p = c.getParentNode();
+ p != null;
+ c = p, p = p.getParentNode())
+ {
+ if (p == fStartContainer)
+ return traverseCommonStartContainer( c, how );
+ ++endContainerDepth;
+ }
+
+ // case 3: Child C of container B is ancestor of A
+ // This can be quickly tested by walking the parent chain of A
+ int startContainerDepth = 0;
+ for ( Node c = fStartContainer, p = c.getParentNode();
+ p != null;
+ c = p, p = p.getParentNode())
+ {
+ if (p == fEndContainer)
+ return traverseCommonEndContainer( c, how );
+ ++startContainerDepth;
+ }
+
+ // case 4: There is a common ancestor container. Find the
+ // ancestor siblings that are children of that container.
+ int depthDiff = startContainerDepth - endContainerDepth;
+
+ Node startNode = fStartContainer;
+ while (depthDiff > 0) {
+ startNode = startNode.getParentNode();
+ depthDiff--;
+ }
+
+ Node endNode = fEndContainer;
+ while (depthDiff < 0) {
+ endNode = endNode.getParentNode();
+ depthDiff++;
+ }
+
+ // ascend the ancestor hierarchy until we have a common parent.
+ for( Node sp = startNode.getParentNode(), ep = endNode.getParentNode();
+ sp!=ep;
+ sp = sp.getParentNode(), ep = ep.getParentNode() )
+ {
+ startNode = sp;
+ endNode = ep;
+ }
+ return traverseCommonAncestors( startNode, endNode, how );
+ }
+
+ /**
+ * Visits the nodes selected by this range when we know
+ * a-priori that the start and end containers are the same.
+ * This method is invoked by the generic traverse
+ * method.
+ *
+ * @param how Specifies what type of traversal is being
+ * requested (extract, clone, or delete).
+ * Legal values for this argument are:
+ *
+ *
+ * EXTRACT_CONTENTS - will produce
+ * a document fragment containing the range's content.
+ * Partially selected nodes are copied, but fully
+ * selected nodes are moved.
+ *
+ * CLONE_CONTENTS - will leave the
+ * context tree of the range undisturbed, but sill
+ * produced cloned content in a document fragment
+ *
+ * DELETE_CONTENTS - will delete from
+ * the context tree of the range, all fully selected
+ * nodes.
+ *
+ *
+ * @return Returns a document fragment containing any
+ * copied or extracted nodes. If the how
+ * parameter was DELETE_CONTENTS , the
+ * return value is null.
+ */
+ private DocumentFragment traverseSameContainer( int how )
+ {
+ DocumentFragment frag = null;
+ if (how != DELETE_CONTENTS) {
+ frag = fDocument.createDocumentFragment();
+ }
+
+ // If selection is empty, just return the fragment
+ if (fStartOffset == fEndOffset) {
+ return frag;
+ }
+
+ // Text, CDATASection, Comment and ProcessingInstruction nodes need special case handling
+ final short nodeType = fStartContainer.getNodeType();
+ if (nodeType == Node.TEXT_NODE ||
+ nodeType == Node.CDATA_SECTION_NODE ||
+ nodeType == Node.COMMENT_NODE ||
+ nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
+ // get the substring
+ String s = fStartContainer.getNodeValue();
+ String sub = s.substring(fStartOffset, fEndOffset);
+
+ // set the original text node to its new value
+ if (how != CLONE_CONTENTS) {
+ ((CharacterDataImpl)fStartContainer).deleteData(fStartOffset,
+ fEndOffset-fStartOffset);
+ // Nothing is partially selected, so collapse to start point
+ collapse(true);
+ }
+ if (how == DELETE_CONTENTS) {
+ return null;
+ }
+ if (nodeType == Node.TEXT_NODE) {
+ frag.appendChild(fDocument.createTextNode(sub));
+ }
+ else if (nodeType == Node.CDATA_SECTION_NODE) {
+ frag.appendChild(fDocument.createCDATASection(sub));
+ }
+ else if (nodeType == Node.COMMENT_NODE) {
+ frag.appendChild(fDocument.createComment(sub));
+ }
+ else { // nodeType == Node.PROCESSING_INSTRUCTION_NODE
+ frag.appendChild(fDocument.createProcessingInstruction(fStartContainer.getNodeName(), sub));
+ }
+ return frag;
+ }
+
+ // Copy nodes between the start/end offsets.
+ Node n = getSelectedNode( fStartContainer, fStartOffset );
+ int cnt = fEndOffset - fStartOffset;
+ while( cnt > 0 ) {
+ Node sibling = n.getNextSibling();
+ Node xferNode = traverseFullySelected( n, how );
+ if ( frag!=null )
+ frag.appendChild( xferNode );
+ --cnt;
+ n = sibling;
+ }
+
+ // Nothing is partially selected, so collapse to start point
+ if (how != CLONE_CONTENTS) {
+ collapse(true);
+ }
+ return frag;
+ }
+
+ /**
+ * Visits the nodes selected by this range when we know
+ * a-priori that the start and end containers are not the
+ * same, but the start container is an ancestor of the
+ * end container. This method is invoked by the generic
+ * traverse method.
+ *
+ * @param endAncestor
+ * The ancestor of the end container that is a direct child
+ * of the start container.
+ *
+ * @param how Specifies what type of traversal is being
+ * requested (extract, clone, or delete).
+ * Legal values for this argument are:
+ *
+ *
+ * EXTRACT_CONTENTS - will produce
+ * a document fragment containing the range's content.
+ * Partially selected nodes are copied, but fully
+ * selected nodes are moved.
+ *
+ * CLONE_CONTENTS - will leave the
+ * context tree of the range undisturbed, but sill
+ * produced cloned content in a document fragment
+ *
+ * DELETE_CONTENTS - will delete from
+ * the context tree of the range, all fully selected
+ * nodes.
+ *
+ *
+ * @return Returns a document fragment containing any
+ * copied or extracted nodes. If the how
+ * parameter was DELETE_CONTENTS , the
+ * return value is null.
+ */
+ private DocumentFragment
+ traverseCommonStartContainer( Node endAncestor, int how )
+ {
+ DocumentFragment frag = null;
+ if ( how!=DELETE_CONTENTS)
+ frag = fDocument.createDocumentFragment();
+ Node n = traverseRightBoundary( endAncestor, how );
+ if ( frag!=null )
+ frag.appendChild( n );
+
+ int endIdx = indexOf( endAncestor, fStartContainer );
+ int cnt = endIdx - fStartOffset;
+ if ( cnt <=0 )
+ {
+ // Collapse to just before the endAncestor, which
+ // is partially selected.
+ if ( how != CLONE_CONTENTS )
+ {
+ setEndBefore( endAncestor );
+ collapse( false );
+ }
+ return frag;
+ }
+
+ n = endAncestor.getPreviousSibling();
+ while( cnt > 0 )
+ {
+ Node sibling = n.getPreviousSibling();
+ Node xferNode = traverseFullySelected( n, how );
+ if ( frag!=null )
+ frag.insertBefore( xferNode, frag.getFirstChild() );
+ --cnt;
+ n = sibling;
+ }
+ // Collapse to just before the endAncestor, which
+ // is partially selected.
+ if ( how != CLONE_CONTENTS )
+ {
+ setEndBefore( endAncestor );
+ collapse( false );
+ }
+ return frag;
+ }
+
+ /**
+ * Visits the nodes selected by this range when we know
+ * a-priori that the start and end containers are not the
+ * same, but the end container is an ancestor of the
+ * start container. This method is invoked by the generic
+ * traverse method.
+ *
+ * @param startAncestor
+ * The ancestor of the start container that is a direct
+ * child of the end container.
+ *
+ * @param how Specifies what type of traversal is being
+ * requested (extract, clone, or delete).
+ * Legal values for this argument are:
+ *
+ *
+ * EXTRACT_CONTENTS - will produce
+ * a document fragment containing the range's content.
+ * Partially selected nodes are copied, but fully
+ * selected nodes are moved.
+ *
+ * CLONE_CONTENTS - will leave the
+ * context tree of the range undisturbed, but sill
+ * produced cloned content in a document fragment
+ *
+ * DELETE_CONTENTS - will delete from
+ * the context tree of the range, all fully selected
+ * nodes.
+ *
+ *
+ * @return Returns a document fragment containing any
+ * copied or extracted nodes. If the how
+ * parameter was DELETE_CONTENTS , the
+ * return value is null.
+ */
+ private DocumentFragment
+ traverseCommonEndContainer( Node startAncestor, int how )
+ {
+ DocumentFragment frag = null;
+ if ( how!=DELETE_CONTENTS)
+ frag = fDocument.createDocumentFragment();
+ Node n = traverseLeftBoundary( startAncestor, how );
+ if ( frag!=null )
+ frag.appendChild( n );
+ int startIdx = indexOf( startAncestor, fEndContainer );
+ ++startIdx; // Because we already traversed it....
+
+ int cnt = fEndOffset - startIdx;
+ n = startAncestor.getNextSibling();
+ while( cnt > 0 )
+ {
+ Node sibling = n.getNextSibling();
+ Node xferNode = traverseFullySelected( n, how );
+ if ( frag!=null )
+ frag.appendChild( xferNode );
+ --cnt;
+ n = sibling;
+ }
+
+ if ( how != CLONE_CONTENTS )
+ {
+ setStartAfter( startAncestor );
+ collapse( true );
+ }
+
+ return frag;
+ }
+
+ /**
+ * Visits the nodes selected by this range when we know
+ * a-priori that the start and end containers are not
+ * the same, and we also know that neither the start
+ * nor end container is an ancestor of the other.
+ * This method is invoked by
+ * the generic traverse method.
+ *
+ * @param startAncestor
+ * Given a common ancestor of the start and end containers,
+ * this parameter is the ancestor (or self) of the start
+ * container that is a direct child of the common ancestor.
+ *
+ * @param endAncestor
+ * Given a common ancestor of the start and end containers,
+ * this parameter is the ancestor (or self) of the end
+ * container that is a direct child of the common ancestor.
+ *
+ * @param how Specifies what type of traversal is being
+ * requested (extract, clone, or delete).
+ * Legal values for this argument are:
+ *
+ *
+ * EXTRACT_CONTENTS - will produce
+ * a document fragment containing the range's content.
+ * Partially selected nodes are copied, but fully
+ * selected nodes are moved.
+ *
+ * CLONE_CONTENTS - will leave the
+ * context tree of the range undisturbed, but sill
+ * produced cloned content in a document fragment
+ *
+ * DELETE_CONTENTS - will delete from
+ * the context tree of the range, all fully selected
+ * nodes.
+ *
+ *
+ * @return Returns a document fragment containing any
+ * copied or extracted nodes. If the how
+ * parameter was DELETE_CONTENTS , the
+ * return value is null.
+ */
+ private DocumentFragment
+ traverseCommonAncestors( Node startAncestor, Node endAncestor, int how )
+ {
+ DocumentFragment frag = null;
+ if ( how!=DELETE_CONTENTS)
+ frag = fDocument.createDocumentFragment();
+
+ Node n = traverseLeftBoundary( startAncestor, how );
+ if ( frag!=null )
+ frag.appendChild( n );
+
+ Node commonParent = startAncestor.getParentNode();
+ int startOffset = indexOf( startAncestor, commonParent );
+ int endOffset = indexOf( endAncestor, commonParent );
+ ++startOffset;
+
+ int cnt = endOffset - startOffset;
+ Node sibling = startAncestor.getNextSibling();
+
+ while( cnt > 0 )
+ {
+ Node nextSibling = sibling.getNextSibling();
+ n = traverseFullySelected( sibling, how );
+ if ( frag!=null )
+ frag.appendChild( n );
+ sibling = nextSibling;
+ --cnt;
+ }
+
+ n = traverseRightBoundary( endAncestor, how );
+ if ( frag!=null )
+ frag.appendChild( n );
+
+ if ( how != CLONE_CONTENTS )
+ {
+ setStartAfter( startAncestor );
+ collapse( true );
+ }
+ return frag;
+ }
+
+ /**
+ * Traverses the "right boundary" of this range and
+ * operates on each "boundary node" according to the
+ * how parameter. It is a-priori assumed
+ * by this method that the right boundary does
+ * not contain the range's start container.
+ *
+ * A "right boundary" is best visualized by thinking
+ * of a sample tree:
+ * A
+ * /|\
+ * / | \
+ * / | \
+ * B C D
+ * /|\ /|\
+ * E F G H I J
+ *
+ * Imagine first a range that begins between the
+ * "E" and "F" nodes and ends between the
+ * "I" and "J" nodes. The start container is
+ * "B" and the end container is "D". Given this setup,
+ * the following applies:
+ *
+ * Partially Selected Nodes: B, D
+ * Fully Selected Nodes: F, G, C, H, I
+ *
+ * The "right boundary" is the highest subtree node
+ * that contains the ending container. The root of
+ * this subtree is always partially selected.
+ *
+ * In this example, the nodes that are traversed
+ * as "right boundary" nodes are: H, I, and D.
+ *
+ * @param root The node that is the root of the "right boundary" subtree.
+ *
+ * @param how Specifies what type of traversal is being
+ * requested (extract, clone, or delete).
+ * Legal values for this argument are:
+ *
+ *
+ * EXTRACT_CONTENTS - will produce
+ * a node containing the boundaries content.
+ * Partially selected nodes are copied, but fully
+ * selected nodes are moved.
+ *
+ * CLONE_CONTENTS - will leave the
+ * context tree of the range undisturbed, but will
+ * produced cloned content.
+ *
+ * DELETE_CONTENTS - will delete from
+ * the context tree of the range, all fully selected
+ * nodes within the boundary.
+ *
+ *
+ * @return Returns a node that is the result of visiting nodes.
+ * If the traversal operation is
+ * DELETE_CONTENTS the return value is null.
+ */
+ private Node traverseRightBoundary( Node root, int how )
+ {
+ Node next = getSelectedNode( fEndContainer, fEndOffset-1 );
+ boolean isFullySelected = ( next!=fEndContainer );
+
+ if ( next==root )
+ return traverseNode( next, isFullySelected, false, how );
+
+ Node parent = next.getParentNode();
+ Node clonedParent = traverseNode( parent, false, false, how );
+
+ while( parent!=null )
+ {
+ while( next!=null )
+ {
+ Node prevSibling = next.getPreviousSibling();
+ Node clonedChild =
+ traverseNode( next, isFullySelected, false, how );
+ if ( how!=DELETE_CONTENTS )
+ {
+ clonedParent.insertBefore(
+ clonedChild,
+ clonedParent.getFirstChild()
+ );
+ }
+ isFullySelected = true;
+ next = prevSibling;
+ }
+ if ( parent==root )
+ return clonedParent;
+
+ next = parent.getPreviousSibling();
+ parent = parent.getParentNode();
+ Node clonedGrandParent = traverseNode( parent, false, false, how );
+ if ( how!=DELETE_CONTENTS )
+ clonedGrandParent.appendChild( clonedParent );
+ clonedParent = clonedGrandParent;
+
+ }
+
+ // should never occur
+ return null;
+ }
+
+ /**
+ * Traverses the "left boundary" of this range and
+ * operates on each "boundary node" according to the
+ * how parameter. It is a-priori assumed
+ * by this method that the left boundary does
+ * not contain the range's end container.
+ *
+ * A "left boundary" is best visualized by thinking
+ * of a sample tree:
+ *
+ * A
+ * /|\
+ * / | \
+ * / | \
+ * B C D
+ * /|\ /|\
+ * E F G H I J
+ *
+ * Imagine first a range that begins between the
+ * "E" and "F" nodes and ends between the
+ * "I" and "J" nodes. The start container is
+ * "B" and the end container is "D". Given this setup,
+ * the following applies:
+ *
+ * Partially Selected Nodes: B, D
+ * Fully Selected Nodes: F, G, C, H, I
+ *
+ * The "left boundary" is the highest subtree node
+ * that contains the starting container. The root of
+ * this subtree is always partially selected.
+ *
+ * In this example, the nodes that are traversed
+ * as "left boundary" nodes are: F, G, and B.
+ *
+ * @param root The node that is the root of the "left boundary" subtree.
+ *
+ * @param how Specifies what type of traversal is being
+ * requested (extract, clone, or delete).
+ * Legal values for this argument are:
+ *
+ *
+ * EXTRACT_CONTENTS - will produce
+ * a node containing the boundaries content.
+ * Partially selected nodes are copied, but fully
+ * selected nodes are moved.
+ *
+ * CLONE_CONTENTS - will leave the
+ * context tree of the range undisturbed, but will
+ * produced cloned content.
+ *
+ * DELETE_CONTENTS - will delete from
+ * the context tree of the range, all fully selected
+ * nodes within the boundary.
+ *
+ *
+ * @return Returns a node that is the result of visiting nodes.
+ * If the traversal operation is
+ * DELETE_CONTENTS the return value is null.
+ */
+ private Node traverseLeftBoundary( Node root, int how )
+ {
+ Node next = getSelectedNode( getStartContainer(), getStartOffset() );
+ boolean isFullySelected = ( next!=getStartContainer() );
+
+ if ( next==root )
+ return traverseNode( next, isFullySelected, true, how );
+
+ Node parent = next.getParentNode();
+ Node clonedParent = traverseNode( parent, false, true, how );
+
+ while( parent!=null )
+ {
+ while( next!=null )
+ {
+ Node nextSibling = next.getNextSibling();
+ Node clonedChild =
+ traverseNode( next, isFullySelected, true, how );
+ if ( how!=DELETE_CONTENTS )
+ clonedParent.appendChild(clonedChild);
+ isFullySelected = true;
+ next = nextSibling;
+ }
+ if ( parent==root )
+ return clonedParent;
+
+ next = parent.getNextSibling();
+ parent = parent.getParentNode();
+ Node clonedGrandParent = traverseNode( parent, false, true, how );
+ if ( how!=DELETE_CONTENTS )
+ clonedGrandParent.appendChild( clonedParent );
+ clonedParent = clonedGrandParent;
+
+ }
+
+ // should never occur
+ return null;
+
+ }
+
+ /**
+ * Utility method for traversing a single node.
+ * Does not properly handle a text node containing both the
+ * start and end offsets. Such nodes should
+ * have been previously detected and been routed to traverseCharacterDataNode.
+ *
+ * @param n The node to be traversed.
+ *
+ * @param isFullySelected
+ * Set to true if the node is fully selected. Should be
+ * false otherwise.
+ * Note that although the DOM 2 specification says that a
+ * text node that is boththe start and end container is not
+ * selected, we treat it here as if it were partially
+ * selected.
+ *
+ * @param isLeft Is true if we are traversing the node as part of navigating
+ * the "left boundary" of the range. If this value is false,
+ * it implies we are navigating the "right boundary" of the
+ * range.
+ *
+ * @param how Specifies what type of traversal is being
+ * requested (extract, clone, or delete).
+ * Legal values for this argument are:
+ *
+ *
+ * EXTRACT_CONTENTS - will simply
+ * return the original node.
+ *
+ * CLONE_CONTENTS - will leave the
+ * context tree of the range undisturbed, but will
+ * return a cloned node.
+ *
+ * DELETE_CONTENTS - will delete the
+ * node from it's parent, but will return null.
+ *
+ *
+ * @return Returns a node that is the result of visiting the node.
+ * If the traversal operation is
+ * DELETE_CONTENTS the return value is null.
+ */
+ private Node traverseNode( Node n, boolean isFullySelected, boolean isLeft, int how )
+ {
+ if ( isFullySelected ) {
+ return traverseFullySelected( n, how );
+ }
+ final short nodeType = n.getNodeType();
+ if (nodeType == Node.TEXT_NODE ||
+ nodeType == Node.CDATA_SECTION_NODE ||
+ nodeType == Node.COMMENT_NODE ||
+ nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
+ return traverseCharacterDataNode( n, isLeft, how );
+ }
+ return traversePartiallySelected( n, how );
+ }
+
+ /**
+ * Utility method for traversing a single node when
+ * we know a-priori that the node if fully
+ * selected.
+ *
+ * @param n The node to be traversed.
+ *
+ * @param how Specifies what type of traversal is being
+ * requested (extract, clone, or delete).
+ * Legal values for this argument are:
+ *
+ *
+ * EXTRACT_CONTENTS - will simply
+ * return the original node.
+ *
+ * CLONE_CONTENTS - will leave the
+ * context tree of the range undisturbed, but will
+ * return a cloned node.
+ *
+ * DELETE_CONTENTS - will delete the
+ * node from it's parent, but will return null.
+ *
+ *
+ * @return Returns a node that is the result of visiting the node.
+ * If the traversal operation is
+ * DELETE_CONTENTS the return value is null.
+ */
+ private Node traverseFullySelected( Node n, int how )
+ {
+ switch( how )
+ {
+ case CLONE_CONTENTS:
+ return n.cloneNode( true );
+ case EXTRACT_CONTENTS:
+ if ( n.getNodeType()==Node.DOCUMENT_TYPE_NODE )
+ {
+ // TBD: This should be a HIERARCHY_REQUEST_ERR
+ throw new DOMException(
+ DOMException.HIERARCHY_REQUEST_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null));
+ }
+ return n;
+ case DELETE_CONTENTS:
+ n.getParentNode().removeChild(n);
+ return null;
+ }
+ return null;
+ }
+
+ /**
+ * Utility method for traversing a single node when
+ * we know a-priori that the node if partially
+ * selected and is not a text node.
+ *
+ * @param n The node to be traversed.
+ *
+ * @param how Specifies what type of traversal is being
+ * requested (extract, clone, or delete).
+ * Legal values for this argument are:
+ *
+ *
+ * EXTRACT_CONTENTS - will simply
+ * return the original node.
+ *
+ * CLONE_CONTENTS - will leave the
+ * context tree of the range undisturbed, but will
+ * return a cloned node.
+ *
+ * DELETE_CONTENTS - will delete the
+ * node from it's parent, but will return null.
+ *
+ *
+ * @return Returns a node that is the result of visiting the node.
+ * If the traversal operation is
+ * DELETE_CONTENTS the return value is null.
+ */
+ private Node traversePartiallySelected( Node n, int how )
+ {
+ switch( how )
+ {
+ case DELETE_CONTENTS:
+ return null;
+ case CLONE_CONTENTS:
+ case EXTRACT_CONTENTS:
+ return n.cloneNode( false );
+ }
+ return null;
+ }
+
+ /**
+ * Utility method for traversing a node containing character data
+ * (either a Text, CDATASection, Comment or ProcessingInstruction node)
+ * that we know a-priori to be on a left or right boundary of the range.
+ * This method does not properly handle text nodes that contain
+ * both the start and end points of the range.
+ *
+ * @param n The node to be traversed.
+ *
+ * @param isLeft Is true if we are traversing the node as part of navigating
+ * the "left boundary" of the range. If this value is false,
+ * it implies we are navigating the "right boundary" of the
+ * range.
+ *
+ * @param how Specifies what type of traversal is being
+ * requested (extract, clone, or delete).
+ * Legal values for this argument are:
+ *
+ *
+ * EXTRACT_CONTENTS - will simply
+ * return the original node.
+ *
+ * CLONE_CONTENTS - will leave the
+ * context tree of the range undisturbed, but will
+ * return a cloned node.
+ *
+ * DELETE_CONTENTS - will delete the
+ * node from it's parent, but will return null.
+ *
+ *
+ * @return Returns a node that is the result of visiting the node.
+ * If the traversal operation is
+ * DELETE_CONTENTS the return value is null.
+ */
+ private Node traverseCharacterDataNode( Node n, boolean isLeft, int how )
+ {
+ String txtValue = n.getNodeValue();
+ String newNodeValue;
+ String oldNodeValue;
+
+ if ( isLeft )
+ {
+ int offset = getStartOffset();
+ newNodeValue = txtValue.substring( offset );
+ oldNodeValue = txtValue.substring( 0, offset );
+ }
+ else
+ {
+ int offset = getEndOffset();
+ newNodeValue = txtValue.substring( 0, offset );
+ oldNodeValue = txtValue.substring( offset );
+ }
+
+ if ( how != CLONE_CONTENTS )
+ n.setNodeValue( oldNodeValue );
+ if ( how==DELETE_CONTENTS )
+ return null;
+ Node newNode = n.cloneNode( false );
+ newNode.setNodeValue( newNodeValue );
+ return newNode;
+ }
+
+ void checkIndex(Node refNode, int offset) throws DOMException
+ {
+ if (offset < 0) {
+ throw new DOMException(
+ DOMException.INDEX_SIZE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null));
+ }
+
+ int type = refNode.getNodeType();
+
+ // If the node contains text, ensure that the
+ // offset of the range is <= to the length of the text
+ if (type == Node.TEXT_NODE
+ || type == Node.CDATA_SECTION_NODE
+ || type == Node.COMMENT_NODE
+ || type == Node.PROCESSING_INSTRUCTION_NODE) {
+ if (offset > refNode.getNodeValue().length()) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null));
+ }
+ }
+ else {
+ // Since the node is not text, ensure that the offset
+ // is valid with respect to the number of child nodes
+ if (offset > refNode.getChildNodes().getLength()) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null));
+ }
+ }
+ }
+
+ /**
+ * Given a node, calculate what the Range's root container
+ * for that node would be.
+ */
+ private Node getRootContainer( Node node )
+ {
+ if ( node==null )
+ return null;
+
+ while( node.getParentNode()!=null )
+ node = node.getParentNode();
+ return node;
+ }
+
+ /**
+ * Returns true IFF the given node can serve as a container
+ * for a range's boundary points.
+ */
+ private boolean isLegalContainer( Node node )
+ {
+ if ( node==null )
+ return false;
+
+ while( node!=null )
+ {
+ switch( node.getNodeType() )
+ {
+ case Node.ENTITY_NODE:
+ case Node.NOTATION_NODE:
+ case Node.DOCUMENT_TYPE_NODE:
+ return false;
+ }
+ node = node.getParentNode();
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Finds the root container for the given node and determines
+ * if that root container is legal with respect to the
+ * DOM 2 specification. At present, that means the root
+ * container must be either an attribute, a document,
+ * or a document fragment.
+ */
+ private boolean hasLegalRootContainer( Node node )
+ {
+ if ( node==null )
+ return false;
+
+ Node rootContainer = getRootContainer( node );
+ switch( rootContainer.getNodeType() )
+ {
+ case Node.ATTRIBUTE_NODE:
+ case Node.DOCUMENT_NODE:
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true IFF the given node can be contained by
+ * a range.
+ */
+ private boolean isLegalContainedNode( Node node )
+ {
+ if ( node==null )
+ return false;
+ switch( node.getNodeType() )
+ {
+ case Node.DOCUMENT_NODE:
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ case Node.ATTRIBUTE_NODE:
+ case Node.ENTITY_NODE:
+ case Node.NOTATION_NODE:
+ return false;
+ }
+ return true;
+ }
+
+ Node nextNode(Node node, boolean visitChildren) {
+
+ if (node == null) return null;
+
+ Node result;
+ if (visitChildren) {
+ result = node.getFirstChild();
+ if (result != null) {
+ return result;
+ }
+ }
+
+ // if hasSibling, return sibling
+ result = node.getNextSibling();
+ if (result != null) {
+ return result;
+ }
+
+
+ // return parent's 1st sibling.
+ Node parent = node.getParentNode();
+ while (parent != null
+ && parent != fDocument
+ ) {
+ result = parent.getNextSibling();
+ if (result != null) {
+ return result;
+ } else {
+ parent = parent.getParentNode();
+ }
+
+ } // while (parent != null && parent != fRoot) {
+
+ // end of list, return null
+ return null;
+ }
+
+ /** is a an ancestor of b ? */
+ boolean isAncestorOf(Node a, Node b) {
+ for (Node node=b; node != null; node=node.getParentNode()) {
+ if (node == a) return true;
+ }
+ return false;
+ }
+
+ /** what is the index of the child in the parent */
+ int indexOf(Node child, Node parent) {
+ if (child.getParentNode() != parent) return -1;
+ int i = 0;
+ for(Node node = parent.getFirstChild(); node!= child; node=node.getNextSibling()) {
+ i++;
+ }
+ return i;
+ }
+
+ /**
+ * Utility method to retrieve a child node by index. This method
+ * assumes the caller is trying to find out which node is
+ * selected by the given index. Note that if the index is
+ * greater than the number of children, this implies that the
+ * first node selected is the parent node itself.
+ *
+ * @param container A container node
+ *
+ * @param offset An offset within the container for which a selected node should
+ * be computed. If the offset is less than zero, or if the offset
+ * is greater than the number of children, the container is returned.
+ *
+ * @return Returns either a child node of the container or the
+ * container itself.
+ */
+ private Node getSelectedNode( Node container, int offset )
+ {
+ if ( container.getNodeType() == Node.TEXT_NODE )
+ return container;
+
+ // This case is an important convenience for
+ // traverseRightBoundary()
+ if ( offset<0 )
+ return container;
+
+ Node child = container.getFirstChild();
+ while( child!=null && offset > 0 )
+ {
+ --offset;
+ child = child.getNextSibling();
+ }
+ if ( child!=null )
+ return child;
+ return container;
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/SecuritySupport.java b/resources/xerces2-j-src/org/apache/xerces/dom/SecuritySupport.java
new file mode 100644
index 0000000..43a49ad
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/SecuritySupport.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * This class is duplicated for each subpackage so keep it in sync.
+ * It is package private and therefore is not exposed as part of any API.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+final class SecuritySupport {
+
+ static ClassLoader getContextClassLoader() {
+ return (ClassLoader)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ ClassLoader cl = null;
+ try {
+ cl = Thread.currentThread().getContextClassLoader();
+ } catch (SecurityException ex) { }
+ return cl;
+ }
+ });
+ }
+
+ static ClassLoader getSystemClassLoader() {
+ return (ClassLoader)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ ClassLoader cl = null;
+ try {
+ cl = ClassLoader.getSystemClassLoader();
+ } catch (SecurityException ex) {}
+ return cl;
+ }
+ });
+ }
+
+ static ClassLoader getParentClassLoader(final ClassLoader cl) {
+ return (ClassLoader)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ ClassLoader parent = null;
+ try {
+ parent = cl.getParent();
+ } catch (SecurityException ex) {}
+
+ // eliminate loops in case of the boot
+ // ClassLoader returning itself as a parent
+ return (parent == cl) ? null : parent;
+ }
+ });
+ }
+
+ static String getSystemProperty(final String propName) {
+ return (String)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return System.getProperty(propName);
+ }
+ });
+ }
+
+ static FileInputStream getFileInputStream(final File file)
+ throws FileNotFoundException
+ {
+ try {
+ return (FileInputStream)
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws FileNotFoundException {
+ return new FileInputStream(file);
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw (FileNotFoundException)e.getException();
+ }
+ }
+
+ static InputStream getResourceAsStream(final ClassLoader cl,
+ final String name)
+ {
+ return (InputStream)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ InputStream ris;
+ if (cl == null) {
+ ris = ClassLoader.getSystemResourceAsStream(name);
+ } else {
+ ris = cl.getResourceAsStream(name);
+ }
+ return ris;
+ }
+ });
+ }
+
+ static boolean getFileExists(final File f) {
+ return ((Boolean)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return f.exists() ? Boolean.TRUE : Boolean.FALSE;
+ }
+ })).booleanValue();
+ }
+
+ static long getLastModified(final File f) {
+ return ((Long)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return new Long(f.lastModified());
+ }
+ })).longValue();
+ }
+
+ private SecuritySupport () {}
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/TextImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/TextImpl.java
new file mode 100644
index 0000000..ae2c686
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/TextImpl.java
@@ -0,0 +1,658 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+/**
+ * Text nodes hold the non-markup, non-Entity content of
+ * an Element or Attribute.
+ *
+ * When a document is first made available to the DOM, there is only
+ * one Text object for each block of adjacent plain-text. Users (ie,
+ * applications) may create multiple adjacent Texts during editing --
+ * see {@link org.w3c.dom.Element#normalize} for discussion.
+ *
+ * Note that CDATASection is a subclass of Text. This is conceptually
+ * valid, since they're really just two different ways of quoting
+ * characters when they're written out as part of an XML stream.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ * @since PR-DOM-Level-1-19980818.
+ */
+public class TextImpl
+ extends CharacterDataImpl
+ implements CharacterData, Text {
+
+ //
+ // Private Data members
+ //
+
+
+ //
+ // Constants
+ //
+
+ /** Serialization version. */
+ static final long serialVersionUID = -5294980852957403469L;
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor */
+ public TextImpl(){}
+
+ /** Factory constructor. */
+ public TextImpl(CoreDocumentImpl ownerDoc, String data) {
+ super(ownerDoc, data);
+ }
+
+ /**
+ * NON-DOM: resets node and sets specified values for the current node
+ *
+ * @param ownerDoc
+ * @param data
+ */
+ public void setValues(CoreDocumentImpl ownerDoc, String data){
+
+ flags=0;
+ nextSibling = null;
+ previousSibling=null;
+ setOwnerDocument(ownerDoc);
+ super.data = data;
+ }
+ //
+ // Node methods
+ //
+
+ /**
+ * A short integer indicating what type of node this is. The named
+ * constants for this value are defined in the org.w3c.dom.Node interface.
+ */
+ public short getNodeType() {
+ return Node.TEXT_NODE;
+ }
+
+ /** Returns the node name. */
+ public String getNodeName() {
+ return "#text";
+ }
+
+ /**
+ * NON-DOM: Set whether this Text is ignorable whitespace.
+ */
+ public void setIgnorableWhitespace(boolean ignore) {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ isIgnorableWhitespace(ignore);
+
+ } // setIgnorableWhitespace(boolean)
+
+
+ /**
+ * DOM L3 Core CR - Experimental
+ *
+ * Returns whether this text node contains
+ * element content whitespace, often abusively called "ignorable whitespace".
+ * The text node is determined to contain whitespace in element content
+ * during the load of the document or if validation occurs while using
+ * Document.normalizeDocument() .
+ * @since DOM Level 3
+ */
+ public boolean isElementContentWhitespace() {
+ // REVISIT: is this implemenation correct?
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return internalIsIgnorableWhitespace();
+ }
+
+
+ /**
+ * DOM Level 3 WD - Experimental.
+ * Returns all text of Text nodes logically-adjacent text
+ * nodes to this node, concatenated in document order.
+ * @since DOM Level 3
+ */
+ public String getWholeText(){
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ StringBuffer buffer = new StringBuffer();
+ if (data != null && data.length() != 0) {
+ buffer.append(data);
+ }
+
+ // concatenate text of logically adjacent text nodes to the left of this node in the tree
+ getWholeTextBackward(this.getPreviousSibling(), buffer, this.getParentNode());
+ String temp = buffer.toString();
+
+ // clear buffer
+ buffer.setLength(0);
+
+ // concatenate text of logically adjacent text nodes to the right of this node in the tree
+ getWholeTextForward(this.getNextSibling(), buffer, this.getParentNode());
+
+ return temp + buffer.toString();
+
+ }
+
+ /**
+ * internal method taking a StringBuffer in parameter and inserts the
+ * text content at the start of the buffer
+ *
+ * @param buf
+ */
+ protected void insertTextContent(StringBuffer buf) throws DOMException {
+ String content = getNodeValue();
+ if (content != null) {
+ buf.insert(0, content);
+ }
+ }
+
+ /**
+ * Concatenates the text of all logically-adjacent text nodes to the
+ * right of this node
+ * @param node
+ * @param buffer
+ * @param parent
+ * @return true - if execution was stopped because the type of node
+ * other than EntityRef, Text, CDATA is encountered, otherwise
+ * return false
+ */
+ private boolean getWholeTextForward(Node node, StringBuffer buffer, Node parent){
+ // boolean to indicate whether node is a child of an entity reference
+ boolean inEntRef = false;
+
+ if (parent!=null) {
+ inEntRef = parent.getNodeType()==Node.ENTITY_REFERENCE_NODE;
+ }
+
+ while (node != null) {
+ short type = node.getNodeType();
+ if (type == Node.ENTITY_REFERENCE_NODE) {
+ if (getWholeTextForward(node.getFirstChild(), buffer, node)){
+ return true;
+ }
+ }
+ else if (type == Node.TEXT_NODE ||
+ type == Node.CDATA_SECTION_NODE) {
+ ((NodeImpl)node).getTextContent(buffer);
+ }
+ else {
+ return true;
+ }
+
+ node = node.getNextSibling();
+ }
+
+ // if the parent node is an entity reference node, must
+ // check nodes to the right of the parent entity reference node for logically adjacent
+ // text nodes
+ if (inEntRef) {
+ getWholeTextForward(parent.getNextSibling(), buffer, parent.getParentNode());
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Concatenates the text of all logically-adjacent text nodes to the left of
+ * the node
+ * @param node
+ * @param buffer
+ * @param parent
+ * @return true - if execution was stopped because the type of node
+ * other than EntityRef, Text, CDATA is encountered, otherwise
+ * return false
+ */
+ private boolean getWholeTextBackward(Node node, StringBuffer buffer, Node parent){
+
+ // boolean to indicate whether node is a child of an entity reference
+ boolean inEntRef = false;
+ if (parent!=null) {
+ inEntRef = parent.getNodeType()==Node.ENTITY_REFERENCE_NODE;
+ }
+
+ while (node != null) {
+ short type = node.getNodeType();
+ if (type == Node.ENTITY_REFERENCE_NODE) {
+ if (getWholeTextBackward(node.getLastChild(), buffer, node)){
+ return true;
+ }
+ }
+ else if (type == Node.TEXT_NODE ||
+ type == Node.CDATA_SECTION_NODE) {
+ ((TextImpl)node).insertTextContent(buffer);
+ }
+ else {
+ return true;
+ }
+
+ node = node.getPreviousSibling();
+ }
+
+ // if the parent node is an entity reference node, must
+ // check nodes to the left of the parent entity reference node for logically adjacent
+ // text nodes
+ if (inEntRef) {
+ getWholeTextBackward(parent.getPreviousSibling(), buffer, parent.getParentNode());
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Replaces the text of the current node and all logically-adjacent text
+ * nodes with the specified text. All logically-adjacent text nodes are
+ * removed including the current node unless it was the recipient of the
+ * replacement text.
+ *
+ * @param content
+ * The content of the replacing Text node.
+ * @return text - The Text node created with the specified content.
+ * @since DOM Level 3
+ */
+ public Text replaceWholeText(String content) throws DOMException {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+
+ //if the content is null
+ Node parent = this.getParentNode();
+ if (content == null || content.length() == 0) {
+ // remove current node
+ if (parent != null) { // check if node in the tree
+ parent.removeChild(this);
+ }
+ return null;
+ }
+
+ // make sure we can make the replacement
+ if (ownerDocument().errorChecking) {
+ if (!canModifyPrev(this)) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NO_MODIFICATION_ALLOWED_ERR", null));
+ }
+
+ // make sure we can make the replacement
+ if (!canModifyNext(this)) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NO_MODIFICATION_ALLOWED_ERR", null));
+ }
+ }
+
+ //replace the text node
+ Text currentNode = null;
+ if (isReadOnly()) {
+ Text newNode = this.ownerDocument().createTextNode(content);
+ if (parent != null) { // check if node in the tree
+ parent.insertBefore(newNode, this);
+ parent.removeChild(this);
+ currentNode = newNode;
+ } else {
+ return newNode;
+ }
+ } else {
+ this.setData(content);
+ currentNode = this;
+ }
+
+ //check logically-adjacent text nodes
+ Node prev = currentNode.getPreviousSibling();
+ while (prev != null) {
+ //If the logically-adjacent next node can be removed
+ //remove it. A logically adjacent node can be removed if
+ //it is a Text or CDATASection node or an EntityReference with
+ //Text and CDATA only children.
+ if ((prev.getNodeType() == Node.TEXT_NODE)
+ || (prev.getNodeType() == Node.CDATA_SECTION_NODE)
+ || (prev.getNodeType() == Node.ENTITY_REFERENCE_NODE && hasTextOnlyChildren(prev))) {
+ parent.removeChild(prev);
+ prev = currentNode;
+ } else {
+ break;
+ }
+ prev = prev.getPreviousSibling();
+ }
+
+ //check logically-adjacent text nodes
+ Node next = currentNode.getNextSibling();
+ while (next != null) {
+ //If the logically-adjacent next node can be removed
+ //remove it. A logically adjacent node can be removed if
+ //it is a Text or CDATASection node or an EntityReference with
+ //Text and CDATA only children.
+ if ((next.getNodeType() == Node.TEXT_NODE)
+ || (next.getNodeType() == Node.CDATA_SECTION_NODE)
+ || (next.getNodeType() == Node.ENTITY_REFERENCE_NODE && hasTextOnlyChildren(next))) {
+ parent.removeChild(next);
+ next = currentNode;
+ } else {
+ break;
+ }
+ next = next.getNextSibling();
+ }
+
+ return currentNode;
+ }
+
+ /**
+ * If any EntityReference to be removed has descendants that are not
+ * EntityReference, Text, or CDATASection nodes, the replaceWholeText method
+ * must fail before performing any modification of the document, raising a
+ * DOMException with the code NO_MODIFICATION_ALLOWED_ERR. Traverse previous
+ * siblings of the node to be replaced. If a previous sibling is an
+ * EntityReference node, get it's last child. If the last child was a Text
+ * or CDATASection node and its previous siblings are neither a replaceable
+ * EntityReference or Text or CDATASection nodes, return false. IF the last
+ * child was neither Text nor CDATASection nor a replaceable EntityReference
+ * Node, then return true. If the last child was a Text or CDATASection node
+ * any its previous sibling was not or was an EntityReference that did not
+ * contain only Text or CDATASection nodes, return false. Check this
+ * recursively for EntityReference nodes.
+ *
+ * @param node
+ * @return true - can replace text false - can't replace exception must be
+ * raised
+ */
+ private boolean canModifyPrev(Node node) {
+ boolean textLastChild = false;
+
+ Node prev = node.getPreviousSibling();
+
+ while (prev != null) {
+
+ short type = prev.getNodeType();
+
+ if (type == Node.ENTITY_REFERENCE_NODE) {
+ //If the previous sibling was entityreference
+ //check if its content is replaceable
+ Node lastChild = prev.getLastChild();
+
+ //if the entity reference has no children
+ //return false
+ if (lastChild == null) {
+ return false;
+ }
+
+ //The replacement text of the entity reference should
+ //be either only text,cadatsections or replaceable entity
+ //reference nodes or the last child should be neither of these
+ while (lastChild != null) {
+ short lType = lastChild.getNodeType();
+
+ if (lType == Node.TEXT_NODE
+ || lType == Node.CDATA_SECTION_NODE) {
+ textLastChild = true;
+ } else if (lType == Node.ENTITY_REFERENCE_NODE) {
+ if (!canModifyPrev(lastChild)) {
+ return false;
+ } else {
+ //If the EntityReference child contains
+ //only text, or non-text or ends with a
+ //non-text node.
+ textLastChild = true;
+ }
+ } else {
+ //If the last child was replaceable and others are not
+ //Text or CDataSection or replaceable EntityRef nodes
+ //return false.
+ if (textLastChild) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ lastChild = lastChild.getPreviousSibling();
+ }
+ } else if (type == Node.TEXT_NODE
+ || type == Node.CDATA_SECTION_NODE) {
+ //If the previous sibling was text or cdatasection move to next
+ } else {
+ //If the previous sibling was anything but text or
+ //cdatasection or an entity reference, stop search and
+ //return true
+ return true;
+ }
+
+ prev = prev.getPreviousSibling();
+ }
+
+ return true;
+ }
+
+ /**
+ * If any EntityReference to be removed has descendants that are not
+ * EntityReference, Text, or CDATASection nodes, the replaceWholeText method
+ * must fail before performing any modification of the document, raising a
+ * DOMException with the code NO_MODIFICATION_ALLOWED_ERR. Traverse previous
+ * siblings of the node to be replaced. If a previous sibling is an
+ * EntityReference node, get it's last child. If the first child was a Text
+ * or CDATASection node and its next siblings are neither a replaceable
+ * EntityReference or Text or CDATASection nodes, return false. IF the first
+ * child was neither Text nor CDATASection nor a replaceable EntityReference
+ * Node, then return true. If the first child was a Text or CDATASection
+ * node any its next sibling was not or was an EntityReference that did not
+ * contain only Text or CDATASection nodes, return false. Check this
+ * recursively for EntityReference nodes.
+ *
+ * @param node
+ * @return true - can replace text false - can't replace exception must be
+ * raised
+ */
+ private boolean canModifyNext(Node node) {
+ boolean textFirstChild = false;
+
+ Node next = node.getNextSibling();
+ while (next != null) {
+
+ short type = next.getNodeType();
+
+ if (type == Node.ENTITY_REFERENCE_NODE) {
+ //If the previous sibling was entityreference
+ //check if its content is replaceable
+ Node firstChild = next.getFirstChild();
+
+ //if the entity reference has no children
+ //return false
+ if (firstChild == null) {
+ return false;
+ }
+
+ //The replacement text of the entity reference should
+ //be either only text,cadatsections or replaceable entity
+ //reference nodes or the last child should be neither of these
+ while (firstChild != null) {
+ short lType = firstChild.getNodeType();
+
+ if (lType == Node.TEXT_NODE
+ || lType == Node.CDATA_SECTION_NODE) {
+ textFirstChild = true;
+ } else if (lType == Node.ENTITY_REFERENCE_NODE) {
+ if (!canModifyNext(firstChild)) {
+ return false;
+ } else {
+ //If the EntityReference child contains
+ //only text, or non-text or ends with a
+ //non-text node.
+ textFirstChild = true;
+ }
+ } else {
+ //If the first child was replaceable text and next
+ //children are not, then return false
+ if (textFirstChild) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ firstChild = firstChild.getNextSibling();
+ }
+ } else if (type == Node.TEXT_NODE
+ || type == Node.CDATA_SECTION_NODE) {
+ //If the previous sibling was text or cdatasection move to next
+ } else {
+ //If the next sibling was anything but text or
+ //cdatasection or an entity reference, stop search and
+ //return true
+ return true;
+ }
+
+ next = next.getNextSibling();
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if an EntityReference node has Text Only child nodes
+ *
+ * @param node
+ * @return true - Contains text only children
+ */
+ private boolean hasTextOnlyChildren(Node node) {
+
+ Node child = node;
+
+ if (child == null) {
+ return false;
+ }
+
+ child = child.getFirstChild();
+ while (child != null) {
+ int type = child.getNodeType();
+
+ if (type == Node.ENTITY_REFERENCE_NODE) {
+ return hasTextOnlyChildren(child);
+ }
+ else if (type != Node.TEXT_NODE
+ && type != Node.CDATA_SECTION_NODE
+ && type != Node.ENTITY_REFERENCE_NODE) {
+ return false;
+ }
+ child = child.getNextSibling();
+ }
+ return true;
+ }
+
+
+ /**
+ * NON-DOM: Returns whether this Text is ignorable whitespace.
+ */
+ public boolean isIgnorableWhitespace() {
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ return internalIsIgnorableWhitespace();
+
+ } // isIgnorableWhitespace():boolean
+
+
+ //
+ // Text methods
+ //
+
+ /**
+ * Break a text node into two sibling nodes. (Note that if the current node
+ * has no parent, they won't wind up as "siblings" -- they'll both be
+ * orphans.)
+ *
+ * @param offset
+ * The offset at which to split. If offset is at the end of the
+ * available data, the second node will be empty.
+ *
+ * @return A reference to the new node (containing data after the offset
+ * point). The original node will contain data up to that point.
+ *
+ * @throws DOMException(INDEX_SIZE_ERR)
+ * if offset is <0 or >length.
+ *
+ * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR)
+ * if node is read-only.
+ */
+ public Text splitText(int offset)
+ throws DOMException {
+
+ if (isReadOnly()) {
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null));
+ }
+
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ if (offset < 0 || offset > data.length() ) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR,
+ DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null));
+ }
+
+ // split text into two separate nodes
+ Text newText =
+ getOwnerDocument().createTextNode(data.substring(offset));
+ setNodeValue(data.substring(0, offset));
+
+ // insert new text node
+ Node parentNode = getParentNode();
+ if (parentNode != null) {
+ parentNode.insertBefore(newText, nextSibling);
+ }
+
+ return newText;
+
+ } // splitText(int):Text
+
+
+ /**
+ * NON-DOM (used by DOMParser): Reset data for the node.
+ */
+ public void replaceData (String value){
+ data = value;
+ }
+
+
+ /**
+ * NON-DOM (used by DOMParser: Sets data to empty string.
+ * Returns the value the data was set to.
+ */
+ public String removeData (){
+ String olddata=data;
+ data = "";
+ return olddata;
+ }
+
+} // class TextImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/TreeWalkerImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/TreeWalkerImpl.java
new file mode 100644
index 0000000..16e02ab
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/TreeWalkerImpl.java
@@ -0,0 +1,529 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.TreeWalker;
+
+/**
+ * This class implements the TreeWalker interface.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class TreeWalkerImpl implements TreeWalker {
+
+ //
+ // Data
+ //
+
+ /** When TRUE, the children of entites references are returned in the iterator. */
+ private boolean fEntityReferenceExpansion = false;
+ /** The whatToShow mask. */
+ int fWhatToShow = NodeFilter.SHOW_ALL;
+ /** The NodeFilter reference. */
+ NodeFilter fNodeFilter;
+ /** The current Node. */
+ Node fCurrentNode;
+ /** The root Node. */
+ Node fRoot;
+ /** Use Node.isSameNode() to check if one node is the same as another. */
+ private boolean fUseIsSameNode;
+
+ //
+ // Implementation Note: No state is kept except the data above
+ // (fWhatToShow, fNodeFilter, fCurrentNode, fRoot) such that
+ // setters could be created for these data values and the
+ // implementation will still work.
+
+
+ //
+ // Constructor
+ //
+
+ /** Public constructor */
+ public TreeWalkerImpl(Node root,
+ int whatToShow,
+ NodeFilter nodeFilter,
+ boolean entityReferenceExpansion) {
+ fCurrentNode = root;
+ fRoot = root;
+ fUseIsSameNode = useIsSameNode(root);
+ fWhatToShow = whatToShow;
+ fNodeFilter = nodeFilter;
+ fEntityReferenceExpansion = entityReferenceExpansion;
+ }
+
+ public Node getRoot() {
+ return fRoot;
+ }
+
+ /** Return the whatToShow value */
+ public int getWhatToShow() {
+ return fWhatToShow;
+ }
+
+ public void setWhatShow(int whatToShow){
+ fWhatToShow = whatToShow;
+ }
+ /** Return the NodeFilter */
+ public NodeFilter getFilter() {
+ return fNodeFilter;
+ }
+
+ /** Return whether children entity references are included in the iterator. */
+ public boolean getExpandEntityReferences() {
+ return fEntityReferenceExpansion;
+ }
+
+ /** Return the current Node. */
+ public Node getCurrentNode() {
+ return fCurrentNode;
+ }
+ /** Return the current Node. */
+ public void setCurrentNode(Node node) {
+ if (node == null) {
+ String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+ }
+
+ fCurrentNode = node;
+ }
+
+ /** Return the parent Node from the current node,
+ * after applying filter, whatToshow.
+ * If result is not null, set the current Node.
+ */
+ public Node parentNode() {
+
+ if (fCurrentNode == null) return null;
+
+ Node node = getParentNode(fCurrentNode);
+ if (node !=null) {
+ fCurrentNode = node;
+ }
+ return node;
+
+ }
+
+ /** Return the first child Node from the current node,
+ * after applying filter, whatToshow.
+ * If result is not null, set the current Node.
+ */
+ public Node firstChild() {
+
+ if (fCurrentNode == null) return null;
+
+ Node node = getFirstChild(fCurrentNode);
+ if (node !=null) {
+ fCurrentNode = node;
+ }
+ return node;
+ }
+ /** Return the last child Node from the current node,
+ * after applying filter, whatToshow.
+ * If result is not null, set the current Node.
+ */
+ public Node lastChild() {
+
+ if (fCurrentNode == null) return null;
+
+ Node node = getLastChild(fCurrentNode);
+ if (node !=null) {
+ fCurrentNode = node;
+ }
+ return node;
+ }
+
+ /** Return the previous sibling Node from the current node,
+ * after applying filter, whatToshow.
+ * If result is not null, set the current Node.
+ */
+ public Node previousSibling() {
+
+ if (fCurrentNode == null) return null;
+
+ Node node = getPreviousSibling(fCurrentNode);
+ if (node !=null) {
+ fCurrentNode = node;
+ }
+ return node;
+ }
+
+ /** Return the next sibling Node from the current node,
+ * after applying filter, whatToshow.
+ * If result is not null, set the current Node.
+ */
+ public Node nextSibling(){
+ if (fCurrentNode == null) return null;
+
+ Node node = getNextSibling(fCurrentNode);
+ if (node !=null) {
+ fCurrentNode = node;
+ }
+ return node;
+ }
+
+ /** Return the previous Node from the current node,
+ * after applying filter, whatToshow.
+ * If result is not null, set the current Node.
+ */
+ public Node previousNode() {
+ Node result;
+
+ if (fCurrentNode == null) return null;
+
+ // get sibling
+ result = getPreviousSibling(fCurrentNode);
+ if (result == null) {
+ result = getParentNode(fCurrentNode);
+ if (result != null) {
+ fCurrentNode = result;
+ return fCurrentNode;
+ }
+ return null;
+ }
+
+ // get the lastChild of result.
+ Node lastChild = getLastChild(result);
+
+ Node prev = lastChild ;
+ while (lastChild != null) {
+ prev = lastChild ;
+ lastChild = getLastChild(prev) ;
+ }
+
+ lastChild = prev ;
+
+ // if there is a lastChild which passes filters return it.
+ if (lastChild != null) {
+ fCurrentNode = lastChild;
+ return fCurrentNode;
+ }
+
+ // otherwise return the previous sibling.
+ if (result != null) {
+ fCurrentNode = result;
+ return fCurrentNode;
+ }
+
+ // otherwise return null.
+ return null;
+ }
+
+ /** Return the next Node from the current node,
+ * after applying filter, whatToshow.
+ * If result is not null, set the current Node.
+ */
+ public Node nextNode() {
+
+ if (fCurrentNode == null) return null;
+
+ Node result = getFirstChild(fCurrentNode);
+
+ if (result != null) {
+ fCurrentNode = result;
+ return result;
+ }
+
+ result = getNextSibling(fCurrentNode);
+
+ if (result != null) {
+ fCurrentNode = result;
+ return result;
+ }
+
+ // return parent's 1st sibling.
+ Node parent = getParentNode(fCurrentNode);
+ while (parent != null) {
+ result = getNextSibling(parent);
+ if (result != null) {
+ fCurrentNode = result;
+ return result;
+ } else {
+ parent = getParentNode(parent);
+ }
+ }
+
+ // end , return null
+ return null;
+ }
+
+ /** Internal function.
+ * Return the parent Node, from the input node
+ * after applying filter, whatToshow.
+ * The current node is not consulted or set.
+ */
+ Node getParentNode(Node node) {
+
+ if (node == null || isSameNode(node, fRoot)) return null;
+
+ Node newNode = node.getParentNode();
+ if (newNode == null) return null;
+
+ int accept = acceptNode(newNode);
+
+ if (accept == NodeFilter.FILTER_ACCEPT)
+ return newNode;
+ else
+ //if (accept == NodeFilter.SKIP_NODE) // and REJECT too.
+ {
+ return getParentNode(newNode);
+ }
+
+
+ }
+
+ /** Internal function.
+ * Return the nextSibling Node, from the input node
+ * after applying filter, whatToshow.
+ * The current node is not consulted or set.
+ */
+ Node getNextSibling(Node node) {
+ return getNextSibling(node, fRoot);
+ }
+
+ /** Internal function.
+ * Return the nextSibling Node, from the input node
+ * after applying filter, whatToshow.
+ * NEVER TRAVERSES ABOVE THE SPECIFIED ROOT NODE.
+ * The current node is not consulted or set.
+ */
+ Node getNextSibling(Node node, Node root) {
+
+ if (node == null || isSameNode(node, root)) return null;
+
+ Node newNode = node.getNextSibling();
+ if (newNode == null) {
+
+ newNode = node.getParentNode();
+
+ if (newNode == null || isSameNode(newNode, root)) return null;
+
+ int parentAccept = acceptNode(newNode);
+
+ if (parentAccept==NodeFilter.FILTER_SKIP) {
+ return getNextSibling(newNode, root);
+ }
+
+ return null;
+ }
+
+ int accept = acceptNode(newNode);
+
+ if (accept == NodeFilter.FILTER_ACCEPT)
+ return newNode;
+ else
+ if (accept == NodeFilter.FILTER_SKIP) {
+ Node fChild = getFirstChild(newNode);
+ if (fChild == null) {
+ return getNextSibling(newNode, root);
+ }
+ return fChild;
+ }
+ else
+ //if (accept == NodeFilter.REJECT_NODE)
+ {
+ return getNextSibling(newNode, root);
+ }
+
+ } // getNextSibling(Node node) {
+
+ /** Internal function.
+ * Return the previous sibling Node, from the input node
+ * after applying filter, whatToshow.
+ * The current node is not consulted or set.
+ */
+ Node getPreviousSibling(Node node) {
+ return getPreviousSibling(node, fRoot);
+ }
+
+ /** Internal function.
+ * Return the previousSibling Node, from the input node
+ * after applying filter, whatToshow.
+ * NEVER TRAVERSES ABOVE THE SPECIFIED ROOT NODE.
+ * The current node is not consulted or set.
+ */
+ Node getPreviousSibling(Node node, Node root) {
+
+ if (node == null || isSameNode(node, root)) return null;
+
+ Node newNode = node.getPreviousSibling();
+ if (newNode == null) {
+
+ newNode = node.getParentNode();
+ if (newNode == null || isSameNode(newNode, root)) return null;
+
+ int parentAccept = acceptNode(newNode);
+
+ if (parentAccept==NodeFilter.FILTER_SKIP) {
+ return getPreviousSibling(newNode, root);
+ }
+
+ return null;
+ }
+
+ int accept = acceptNode(newNode);
+
+ if (accept == NodeFilter.FILTER_ACCEPT)
+ return newNode;
+ else
+ if (accept == NodeFilter.FILTER_SKIP) {
+ Node fChild = getLastChild(newNode);
+ if (fChild == null) {
+ return getPreviousSibling(newNode, root);
+ }
+ return fChild;
+ }
+ else
+ //if (accept == NodeFilter.REJECT_NODE)
+ {
+ return getPreviousSibling(newNode, root);
+ }
+
+ } // getPreviousSibling(Node node) {
+
+ /** Internal function.
+ * Return the first child Node, from the input node
+ * after applying filter, whatToshow.
+ * The current node is not consulted or set.
+ */
+ Node getFirstChild(Node node) {
+ if (node == null) return null;
+
+ if ( !fEntityReferenceExpansion
+ && node.getNodeType() == Node.ENTITY_REFERENCE_NODE)
+ return null;
+ Node newNode = node.getFirstChild();
+ if (newNode == null) return null;
+ int accept = acceptNode(newNode);
+
+ if (accept == NodeFilter.FILTER_ACCEPT)
+ return newNode;
+ else
+ if (accept == NodeFilter.FILTER_SKIP
+ && newNode.hasChildNodes())
+ {
+ Node fChild = getFirstChild(newNode);
+
+ if (fChild == null) {
+ return getNextSibling(newNode, node);
+ }
+ return fChild;
+ }
+ else
+ //if (accept == NodeFilter.REJECT_NODE)
+ {
+ return getNextSibling(newNode, node);
+ }
+
+
+ }
+
+ /** Internal function.
+ * Return the last child Node, from the input node
+ * after applying filter, whatToshow.
+ * The current node is not consulted or set.
+ */
+ Node getLastChild(Node node) {
+
+ if (node == null) return null;
+
+ if ( !fEntityReferenceExpansion
+ && node.getNodeType() == Node.ENTITY_REFERENCE_NODE)
+ return null;
+
+ Node newNode = node.getLastChild();
+ if (newNode == null) return null;
+
+ int accept = acceptNode(newNode);
+
+ if (accept == NodeFilter.FILTER_ACCEPT)
+ return newNode;
+ else
+ if (accept == NodeFilter.FILTER_SKIP
+ && newNode.hasChildNodes())
+ {
+ Node lChild = getLastChild(newNode);
+ if (lChild == null) {
+ return getPreviousSibling(newNode, node);
+ }
+ return lChild;
+ }
+ else
+ //if (accept == NodeFilter.REJECT_NODE)
+ {
+ return getPreviousSibling(newNode, node);
+ }
+
+
+ }
+
+ /** Internal function.
+ * The node whatToShow and the filter are combined into one result. */
+ short acceptNode(Node node) {
+ /***
+ 7.1.2.4. Filters and whatToShow flags
+
+ Iterator and TreeWalker apply whatToShow flags before applying Filters. If a node is rejected by the
+ active whatToShow flags, a Filter will not be called to evaluate that node. When a node is rejected by
+ the active whatToShow flags, children of that node will still be considered, and Filters may be called to
+ evaluate them.
+ ***/
+
+ if (fNodeFilter == null) {
+ if ( ( fWhatToShow & (1 << node.getNodeType()-1)) != 0) {
+ return NodeFilter.FILTER_ACCEPT;
+ } else {
+ return NodeFilter.FILTER_SKIP;
+ }
+ } else {
+ if ((fWhatToShow & (1 << node.getNodeType()-1)) != 0 ) {
+ return fNodeFilter.acceptNode(node);
+ } else {
+ // What to show has failed. See above excerpt from spec.
+ // Equivalent to FILTER_SKIP.
+ return NodeFilter.FILTER_SKIP;
+ }
+ }
+ }
+
+ /**
+ * Use isSameNode() for testing node identity if the DOM implementation
+ * supports DOM Level 3 core and it isn't the Xerces implementation.
+ */
+ private boolean useIsSameNode(Node node) {
+ if (node instanceof NodeImpl) {
+ return false;
+ }
+ Document doc = node.getNodeType() == Node.DOCUMENT_NODE
+ ? (Document) node : node.getOwnerDocument();
+ return (doc != null && doc.getImplementation().hasFeature("Core", "3.0"));
+ }
+
+ /**
+ * Returns true if m is the same node n .
+ */
+ private boolean isSameNode(Node m, Node n) {
+ return (fUseIsSameNode) ? m.isSameNode(n) : m == n;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/events/EventImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/events/EventImpl.java
new file mode 100644
index 0000000..c3d722f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/events/EventImpl.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom.events;
+
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventTarget;
+
+/**
+ * EventImpl is an implementation of the basic "generic" DOM Level 2 Event
+ * object. It may be subclassed by more specialized event sets.
+ * Note that in our implementation, events are re-dispatchable (dispatch
+ * clears the stopPropagation and preventDefault flags before it starts);
+ * I believe that is the DOM's intent but I don't see an explicit statement
+ * to this effect.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class EventImpl implements Event {
+
+ public String type = null;
+ public EventTarget target;
+ public EventTarget currentTarget;
+ public short eventPhase;
+ public boolean initialized = false, bubbles = true, cancelable = false;
+ public boolean stopPropagation = false, preventDefault = false;
+
+ protected long timeStamp = System.currentTimeMillis();
+
+ /**
+ * The DOM doesn't deal with constructors, so instead we have an
+ * initializer call to set most of the read-only fields. The
+ * others are set, and reset, by the event subsystem during dispatch.
+ *
+ * Note that init() -- and the subclass-specific initWhatever() calls --
+ * may be reinvoked. At least one initialization is required; repeated
+ * initializations overwrite the event with new values of their
+ * parameters.
+ */
+ public void initEvent(String eventTypeArg, boolean canBubbleArg,
+ boolean cancelableArg) {
+ type = eventTypeArg;
+ bubbles = canBubbleArg;
+ cancelable = cancelableArg;
+ initialized = true;
+ }
+
+ /**
+ * @return true iff this Event is of a class and type which supports
+ * bubbling. In the generic case, this is True.
+ */
+ public boolean getBubbles() {
+ return bubbles;
+ }
+
+ /**
+ * @return true iff this Event is of a class and type which (a) has a
+ * Default Behavior in this DOM, and (b)allows cancellation (blocking)
+ * of that behavior. In the generic case, this is False.
+ */
+ public boolean getCancelable() {
+ return cancelable;
+ }
+
+ /**
+ * @return the Node (EventTarget) whose EventListeners are currently
+ * being processed. During capture and bubble phases, this may not be
+ * the target node.
+ */
+ public EventTarget getCurrentTarget() {
+ return currentTarget;
+ }
+
+ /**
+ * @return the current processing phase for this event --
+ * CAPTURING_PHASE, AT_TARGET, BUBBLING_PHASE. (There may be
+ * an internal DEFAULT_PHASE as well, but the users won't see it.)
+ */
+ public short getEventPhase() {
+ return eventPhase;
+ }
+
+ /**
+ * @return the EventTarget (Node) to which the event was originally
+ * dispatched.
+ */
+ public EventTarget getTarget() {
+ return target;
+ }
+
+ /**
+ * @return event name as a string
+ */
+ public String getType() {
+ return type;
+ }
+
+ public long getTimeStamp() {
+ return timeStamp;
+ }
+
+ /**
+ * Causes exit from in-progress event dispatch before the next
+ * currentTarget is selected. Replaces the preventBubble() and
+ * preventCapture() methods which were present in early drafts;
+ * they may be reintroduced in future levels of the DOM.
+ */
+ public void stopPropagation() {
+ stopPropagation = true;
+ }
+
+ /**
+ * Prevents any default processing built into the target node from
+ * occurring.
+ */
+ public void preventDefault() {
+ preventDefault = true;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/events/MouseEventImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/events/MouseEventImpl.java
new file mode 100644
index 0000000..4989568
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/events/MouseEventImpl.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom.events;
+
+import org.w3c.dom.events.EventTarget;
+import org.w3c.dom.events.MouseEvent;
+import org.w3c.dom.views.AbstractView;
+
+/**
+ * An implementation of the DOM Level 2 MouseEvent interface.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class MouseEventImpl
+ extends UIEventImpl
+ implements MouseEvent {
+
+ private int fScreenX;
+ private int fScreenY;
+ private int fClientX;
+ private int fClientY;
+ private boolean fCtrlKey;
+ private boolean fAltKey;
+ private boolean fShiftKey;
+ private boolean fMetaKey;
+ private short fButton;
+ private EventTarget fRelatedTarget;
+
+ public int getScreenX() {
+ return fScreenX;
+ }
+
+ public int getScreenY() {
+ return fScreenY;
+ }
+
+ public int getClientX() {
+ return fClientX;
+ }
+
+ public int getClientY() {
+ return fClientY;
+ }
+
+ public boolean getCtrlKey() {
+ return fCtrlKey;
+ }
+
+ public boolean getAltKey() {
+ return fAltKey;
+ }
+
+ public boolean getShiftKey() {
+ return fShiftKey;
+ }
+
+ public boolean getMetaKey() {
+ return fMetaKey;
+ }
+
+ public short getButton() {
+ return fButton;
+ }
+
+ public EventTarget getRelatedTarget() {
+ return fRelatedTarget;
+ }
+
+ public void initMouseEvent(String typeArg, boolean canBubbleArg, boolean cancelableArg, AbstractView viewArg,
+ int detailArg, int screenXArg, int screenYArg, int clientXArg, int clientYArg,
+ boolean ctrlKeyArg, boolean altKeyArg, boolean shiftKeyArg, boolean metaKeyArg,
+ short buttonArg, EventTarget relatedTargetArg) {
+ fScreenX = screenXArg;
+ fScreenY = screenYArg;
+ fClientX = clientXArg;
+ fClientY = clientYArg;
+ fCtrlKey = ctrlKeyArg;
+ fAltKey = altKeyArg;
+ fShiftKey = shiftKeyArg;
+ fMetaKey = metaKeyArg;
+ fButton = buttonArg;
+ fRelatedTarget = relatedTargetArg;
+ super.initUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/events/MutationEventImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/events/MutationEventImpl.java
new file mode 100644
index 0000000..b977459
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/events/MutationEventImpl.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom.events;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.events.MutationEvent;
+
+/**
+ * An implementation of the DOM Level 2 MutationEvent interface.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class MutationEventImpl
+ extends EventImpl
+ implements MutationEvent {
+
+ Node relatedNode = null;
+ String prevValue = null;
+ String newValue = null;
+ String attrName = null;
+
+ // REVISIT: The DOM Level 2 PR has a bug: the init method should let this
+ // attribute be specified. Since it doesn't we have to give write access.
+ public short attrChange;
+
+ // NON-DOM CONSTANTS: Storage efficiency, avoid risk of typos.
+ public static final String DOM_SUBTREE_MODIFIED = "DOMSubtreeModified";
+ public static final String DOM_NODE_INSERTED = "DOMNodeInserted";
+ public static final String DOM_NODE_REMOVED = "DOMNodeRemoved";
+ public static final String DOM_NODE_REMOVED_FROM_DOCUMENT = "DOMNodeRemovedFromDocument";
+ public static final String DOM_NODE_INSERTED_INTO_DOCUMENT = "DOMNodeInsertedIntoDocument";
+ public static final String DOM_ATTR_MODIFIED = "DOMAttrModified";
+ public static final String DOM_CHARACTER_DATA_MODIFIED = "DOMCharacterDataModified";
+
+ /**
+ * @return the name of the Attr which
+ * changed, for DOMAttrModified events.
+ * Undefined for others.
+ */
+ public String getAttrName() {
+ return attrName;
+ }
+
+ /**
+ * attrChange indicates the type of change which triggered
+ * the DOMAttrModified event. The values can be MODIFICATION
+ * , ADDITION , or REMOVAL .
+ */
+ public short getAttrChange() {
+ return attrChange;
+ }
+
+ /**
+ * @return the new string value of the Attr for DOMAttrModified events, or
+ * of the CharacterData node for DOMCharDataModifed events.
+ * Undefined for others.
+ */
+ public String getNewValue() {
+ return newValue;
+ }
+
+ /**
+ * @return the previous string value of the Attr for DOMAttrModified events, or
+ * of the CharacterData node for DOMCharDataModifed events.
+ * Undefined for others.
+ */
+ public String getPrevValue() {
+ return prevValue;
+ }
+
+ /**
+ * @return a Node related to this event, other than the target that the
+ * node was dispatched to. For DOMNodeRemoved, it is the node which
+ * was removed.
+ * No other uses are currently defined.
+ */
+ public Node getRelatedNode() {
+ return relatedNode;
+ }
+
+ /**
+ * Initialize a mutation event, or overwrite the event's current
+ * settings with new values of the parameters.
+ */
+ public void initMutationEvent(String typeArg, boolean canBubbleArg,
+ boolean cancelableArg, Node relatedNodeArg, String prevValueArg,
+ String newValueArg, String attrNameArg, short attrChangeArg) {
+ relatedNode = relatedNodeArg;
+ prevValue = prevValueArg;
+ newValue = newValueArg;
+ attrName = attrNameArg;
+ attrChange = attrChangeArg;
+ super.initEvent(typeArg, canBubbleArg, cancelableArg);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/events/UIEventImpl.java b/resources/xerces2-j-src/org/apache/xerces/dom/events/UIEventImpl.java
new file mode 100644
index 0000000..b9b0023
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/events/UIEventImpl.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.dom.events;
+
+import org.w3c.dom.events.UIEvent;
+import org.w3c.dom.views.AbstractView;
+
+/**
+ * An implementation of the DOM Level 2 UIEvent interface.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class UIEventImpl
+ extends EventImpl
+ implements UIEvent {
+
+ private AbstractView fView;
+ private int fDetail;
+
+ public AbstractView getView() {
+ return fView;
+ }
+
+ public int getDetail() {
+ return fDetail;
+ }
+
+ public void initUIEvent(String typeArg, boolean canBubbleArg, boolean cancelableArg,
+ AbstractView viewArg, int detailArg) {
+ fView = viewArg;
+ fDetail = detailArg;
+ super.initEvent(typeArg, canBubbleArg, cancelableArg);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/org.apache.xerces.dom.DOMImplementationSourceImpl b/resources/xerces2-j-src/org/apache/xerces/dom/org.apache.xerces.dom.DOMImplementationSourceImpl
new file mode 100644
index 0000000..d92a986
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/org.apache.xerces.dom.DOMImplementationSourceImpl
@@ -0,0 +1 @@
+org.apache.xerces.dom.DOMImplementationSourceImpl
\ No newline at end of file
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom/org.w3c.dom.DOMImplementationSourceList b/resources/xerces2-j-src/org/apache/xerces/dom/org.w3c.dom.DOMImplementationSourceList
new file mode 100644
index 0000000..7a52dd1
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom/org.w3c.dom.DOMImplementationSourceList
@@ -0,0 +1 @@
+org.apache.xerces.dom.DOMXSImplementationSourceImpl
\ No newline at end of file
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASAttributeDeclaration.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASAttributeDeclaration.java
new file mode 100644
index 0000000..0cf018e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASAttributeDeclaration.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+/**
+ * @deprecated
+ * An attribute declaration in the context of a ASObject .The
+ * constant 'REQUIRED' is missing from this interface.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface ASAttributeDeclaration extends ASObject {
+ // VALUE_TYPES
+ /**
+ * Describes that the attribute does not have any value constraint.
+ */
+ public static final short VALUE_NONE = 0;
+ /**
+ * Indicates that the there is a default value constraint.
+ */
+ public static final short VALUE_DEFAULT = 1;
+ /**
+ * Indicates that there is a fixed value constraint for this attribute.
+ */
+ public static final short VALUE_FIXED = 2;
+
+ /**
+ * Datatype of the attribute.
+ */
+ public ASDataType getDataType();
+ /**
+ * Datatype of the attribute.
+ */
+ public void setDataType(ASDataType dataType);
+
+ /**
+ * Default or fixed value.
+ */
+ public String getDataValue();
+ /**
+ * Default or fixed value.
+ */
+ public void setDataValue(String dataValue);
+
+ /**
+ * Valid attribute values, separated by commas, in a string.
+ */
+ public String getEnumAttr();
+ /**
+ * Valid attribute values, separated by commas, in a string.
+ */
+ public void setEnumAttr(String enumAttr);
+
+ /**
+ * Owner elements ASObject of attribute, meaning that an
+ * attribute declaration can be shared by multiple elements.
+ */
+ public ASObjectList getOwnerElements();
+ /**
+ * Owner elements ASObject of attribute, meaning that an
+ * attribute declaration can be shared by multiple elements.
+ */
+ public void setOwnerElements(ASObjectList ownerElements);
+
+ /**
+ * Constraint type if any for this attribute.
+ */
+ public short getDefaultType();
+ /**
+ * Constraint type if any for this attribute.
+ */
+ public void setDefaultType(short defaultType);
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASContentModel.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASContentModel.java
new file mode 100644
index 0000000..10d4f58
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASContentModel.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+/**
+ * @deprecated
+ * The content model of a declared element.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface ASContentModel extends ASObject {
+ /**
+ * Signifies unbounded upper limit. The MAX_VALUE value is
+ * 0xFFFFFFFF FFFFFFFF . This needs to be better defined in
+ * the generated bindings.
+ */
+ public static final int AS_UNBOUNDED = Integer.MAX_VALUE;
+ // ASContentModelType
+ /**
+ * This constant value signifies a sequence operator. For example, in a
+ * DTD, this would be the ', ' operator.
+ */
+ public static final short AS_SEQUENCE = 0;
+ /**
+ * This constant value signifies a choice operator. For example, in a DTD,
+ * this would be the '| ' operator.
+ */
+ public static final short AS_CHOICE = 1;
+ /**
+ * All of the above.
+ */
+ public static final short AS_ALL = 2;
+ /**
+ * None of the above, i.e., neither a choice nor sequence operator.
+ */
+ public static final short AS_NONE = 3;
+
+ /**
+ * One of AS_CHOICE , AS_SEQUENCE ,
+ * AS_ALL or AS_NONE . The operator is applied
+ * to all the components(ASObjects) in the subModels . For
+ * example, if the list operator is AS_CHOICE and the
+ * components in subModels are a, b and c then the abstract schema for
+ * the element being declared is (a|b|c) .
+ */
+ public short getListOperator();
+ /**
+ * One of AS_CHOICE , AS_SEQUENCE ,
+ * AS_ALL or AS_NONE . The operator is applied
+ * to all the components(ASObjects) in the subModels . For
+ * example, if the list operator is AS_CHOICE and the
+ * components in subModels are a, b and c then the abstract schema for
+ * the element being declared is (a|b|c) .
+ */
+ public void setListOperator(short listOperator);
+
+ /**
+ * min occurrence for this content particle. Its value may be 0 or a
+ * positive integer.
+ */
+ public int getMinOccurs();
+ /**
+ * min occurrence for this content particle. Its value may be 0 or a
+ * positive integer.
+ */
+ public void setMinOccurs(int minOccurs);
+
+ /**
+ * maximum occurrence for this content particle. Its value may be
+ * 0 , a positive integer, or AS_UNBOUNDED to
+ * indicate that no upper limit has been set.
+ */
+ public int getMaxOccurs();
+ /**
+ * maximum occurrence for this content particle. Its value may be
+ * 0 , a positive integer, or AS_UNBOUNDED to
+ * indicate that no upper limit has been set.
+ */
+ public void setMaxOccurs(int maxOccurs);
+
+ /**
+ * Pointers to ASObject s such as
+ * ASElementDeclaration s and further
+ * ASContentModel s.
+ */
+ public ASObjectList getSubModels();
+ /**
+ * Pointers to ASObject s such as
+ * ASElementDeclaration s and further
+ * ASContentModel s.
+ */
+ public void setSubModels(ASObjectList subModels);
+
+ /**
+ * Removes the ASObject in the submodel. Nodes that already
+ * exist in the list are moved as needed.
+ * @param oldNode The node to be removed.
+ */
+ public void removesubModel(ASObject oldNode);
+
+ /**
+ * Inserts a new node in the submodel. Nodes that already exist in the
+ * list are moved as needed.
+ * @param newNode The new node to be inserted.
+ * @exception DOMASException
+ * DUPLICATE_NAME_ERR : Raised if a element declaration
+ * already exists with the same name within an AS_CHOICE
+ * operator.
+ */
+ public void insertsubModel(ASObject newNode)
+ throws DOMASException;
+
+ /**
+ * Appends a new node to the end of the list representing the
+ * subModels .
+ * @param newNode The new node to be appended.
+ * @return the length of the subModels .
+ * @exception DOMASException
+ * DUPLICATE_NAME_ERR : Raised if a element declaration
+ * already exists with the same name within an AS_CHOICE
+ * operator.
+ * TYPE_ERR : Raised if type is neither an
+ * ASContentModel nor an ASElementDeclaration
+ * .
+ */
+ public int appendsubModel(ASObject newNode)
+ throws DOMASException;
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASDataType.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASDataType.java
new file mode 100644
index 0000000..d49adb2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASDataType.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+/**
+ * @deprecated
+ * The datatypes supported by DOM AS implementations. Further datatypes may be
+ * added in the Schema/PSVI spec.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface ASDataType {
+ /**
+ * One of the enumerated codes representing the data type.
+ */
+ public short getDataType();
+
+ // DATA_TYPES
+ /**
+ * A code representing the string data type as defined in .
+ */
+ public static final short STRING_DATATYPE = 1;
+ /**
+ * The NOTATION data type as defined in .
+ */
+ public static final short NOTATION_DATATYPE = 10;
+ /**
+ * The ID data type as defined in .
+ */
+ public static final short ID_DATATYPE = 11;
+ /**
+ * The IDREF data type as defined in .
+ */
+ public static final short IDREF_DATATYPE = 12;
+ /**
+ * The IDREFS data type as defined in .
+ */
+ public static final short IDREFS_DATATYPE = 13;
+ /**
+ * The ENTITY data type as defined in .
+ */
+ public static final short ENTITY_DATATYPE = 14;
+ /**
+ * The ENTITIES data type as defined in .
+ */
+ public static final short ENTITIES_DATATYPE = 15;
+ /**
+ * The NMTOKEN data type as defined in .
+ */
+ public static final short NMTOKEN_DATATYPE = 16;
+ /**
+ * The NMTOKENS data type as defined in .
+ */
+ public static final short NMTOKENS_DATATYPE = 17;
+ /**
+ * A code representing the boolean data type as defined in .
+ */
+ public static final short BOOLEAN_DATATYPE = 100;
+ /**
+ * A code representing the float data type as defined in .
+ */
+ public static final short FLOAT_DATATYPE = 101;
+ /**
+ * A code representing the double data type as defined in .
+ */
+ public static final short DOUBLE_DATATYPE = 102;
+ /**
+ * The decimal data type as defined in .
+ */
+ public static final short DECIMAL_DATATYPE = 103;
+ /**
+ * The hexbinary data type as defined in .
+ */
+ public static final short HEXBINARY_DATATYPE = 104;
+ /**
+ * The base64binary data type as defined in .
+ */
+ public static final short BASE64BINARY_DATATYPE = 105;
+ /**
+ * Then uri reference data type as defined in .
+ */
+ public static final short ANYURI_DATATYPE = 106;
+ /**
+ * Then XML qualified name data type as defined in .
+ */
+ public static final short QNAME_DATATYPE = 107;
+ /**
+ * The duration data type as defined in .
+ */
+ public static final short DURATION_DATATYPE = 108;
+ /**
+ * The datetime data type as defined in .
+ */
+ public static final short DATETIME_DATATYPE = 109;
+ /**
+ * The date data type as defined in .
+ */
+ public static final short DATE_DATATYPE = 110;
+ /**
+ * The time data type as defined in .
+ */
+ public static final short TIME_DATATYPE = 111;
+ /**
+ * The yearmonth data type as defined in .
+ */
+ public static final short GYEARMONTH_DATATYPE = 112;
+ /**
+ * The year data type as defined in .
+ */
+ public static final short GYEAR_DATATYPE = 113;
+ /**
+ * The monthday data type as defined in .
+ */
+ public static final short GMONTHDAY_DATATYPE = 114;
+ /**
+ * The day data type as defined in .
+ */
+ public static final short GDAY_DATATYPE = 115;
+ /**
+ * The month data type as defined in .
+ */
+ public static final short GMONTH_DATATYPE = 116;
+ /**
+ * The integer data type as defined in .
+ */
+ public static final short INTEGER = 117;
+ /**
+ * A code representing the Name data type as defined in .
+ */
+ public static final short NAME_DATATYPE = 200;
+ /**
+ * A code representing the NCName data type as defined in .
+ */
+ public static final short NCNAME_DATATYPE = 201;
+ /**
+ * A code representing the Normalized string data type as defined in .
+ */
+ public static final short NORMALIZEDSTRING_DATATYPE = 202;
+ /**
+ * The token data type as defined in .
+ */
+ public static final short TOKEN_DATATYPE = 203;
+ /**
+ * The Language data type as defined in .
+ */
+ public static final short LANGUAGE_DATATYPE = 204;
+ /**
+ * The Non-positive integer data type as defined in .
+ */
+ public static final short NONPOSITIVEINTEGER_DATATYPE = 205;
+ /**
+ * Then negative integer data type as defined in .
+ */
+ public static final short NEGATIVEINTEGER_DATATYPE = 206;
+ /**
+ * Then long data type as defined in .
+ */
+ public static final short LONG_DATATYPE = 207;
+ /**
+ * The integer data type as defined in .
+ */
+ public static final short INT_DATATYPE = 208;
+ /**
+ * The short data type as defined in .
+ */
+ public static final short SHORT_DATATYPE = 209;
+ /**
+ * The byte data type as defined in .
+ */
+ public static final short BYTE_DATATYPE = 210;
+ /**
+ * The non-negative integer data type as defined in .
+ */
+ public static final short NONNEGATIVEINTEGER_DATATYPE = 211;
+ /**
+ * The unsigned long data type as defined in .
+ */
+ public static final short UNSIGNEDLONG_DATATYPE = 212;
+ /**
+ * The unsigned integer data type as defined in .
+ */
+ public static final short UNSIGNEDINT_DATATYPE = 213;
+ /**
+ * The unsigned short data type as defined in .
+ */
+ public static final short UNSIGNEDSHORT_DATATYPE = 214;
+ /**
+ * The unsigned byte data type as defined in .
+ */
+ public static final short UNSIGNEDBYTE_DATATYPE = 215;
+ /**
+ * The positive integer data type as defined in .
+ */
+ public static final short POSITIVEINTEGER_DATATYPE = 216;
+ /**
+ * The other simple data type as defined in .
+ */
+ public static final short OTHER_SIMPLE_DATATYPE = 1000;
+ /**
+ * The user-defined complex data type as defined in .
+ */
+ public static final short COMPLEX_DATATYPE = 1001;
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASElementDeclaration.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASElementDeclaration.java
new file mode 100644
index 0000000..f2915dd
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASElementDeclaration.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+/**
+ * @deprecated
+ * The element name along with the content specification in the context of an
+ * ASObject .
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface ASElementDeclaration extends ASObject {
+ // CONTENT_MODEL_TYPES
+ /**
+ * Represents an EMPTY content type for an Element declaration.
+ */
+ public static final short EMPTY_CONTENTTYPE = 1;
+ /**
+ * Represents an ANY content type for an Element declaration.
+ */
+ public static final short ANY_CONTENTTYPE = 2;
+ /**
+ * Represents a MIXED content type for an Element declaration. Note that
+ * isPCDataOnly would also need to checked, in addition to
+ * this, if an element's content model was simply text, as an example.
+ */
+ public static final short MIXED_CONTENTTYPE = 3;
+ /**
+ * Represents an ELEMENTS only content type for an Element declaration.
+ */
+ public static final short ELEMENTS_CONTENTTYPE = 4;
+
+ /**
+ * A boolean defining whether the element order and number of the child
+ * elements for mixed content type has to be respected or not. For
+ * example XML Schema defined mixed content types the order is important
+ * and needs to be respected whether for DTD based AS the order and
+ * number of child elements are not important.
+ */
+ public boolean getStrictMixedContent();
+ /**
+ * A boolean defining whether the element order and number of the child
+ * elements for mixed content type has to be respected or not. For
+ * example XML Schema defined mixed content types the order is important
+ * and needs to be respected whether for DTD based AS the order and
+ * number of child elements are not important.
+ */
+ public void setStrictMixedContent(boolean strictMixedContent);
+
+ /**
+ * Datatype of the element.
+ */
+ public ASDataType getElementType();
+ /**
+ * Datatype of the element.
+ */
+ public void setElementType(ASDataType elementType);
+
+ /**
+ * Boolean defining whether the element type contains child elements and
+ * PCDATA or PCDATA only for mixed element types. true if
+ * the element is of type PCDATA only. Relevant only for mixed content
+ * type elements.
+ */
+ public boolean getIsPCDataOnly();
+ /**
+ * Boolean defining whether the element type contains child elements and
+ * PCDATA or PCDATA only for mixed element types. true if
+ * the element is of type PCDATA only. Relevant only for mixed content
+ * type elements.
+ */
+ public void setIsPCDataOnly(boolean isPCDataOnly);
+
+ /**
+ * The content type of the element. One of EMPTY_CONTENTTYPE ,
+ * ANY_CONTENTTYPE , MIXED_CONTENTTYPE ,
+ * ELEMENTS_CONTENTTYPE .
+ */
+ public short getContentType();
+ /**
+ * The content type of the element. One of EMPTY_CONTENTTYPE ,
+ * ANY_CONTENTTYPE , MIXED_CONTENTTYPE ,
+ * ELEMENTS_CONTENTTYPE .
+ */
+ public void setContentType(short contentType);
+
+ /**
+ * the URI reference representing the system identifier for the notation
+ * declaration, if present, null otherwise.
+ */
+ public String getSystemId();
+ /**
+ * the URI reference representing the system identifier for the notation
+ * declaration, if present, null otherwise.
+ */
+ public void setSystemId(String systemId);
+
+ /**
+ * The content model of element.
+ */
+ public ASContentModel getAsCM();
+ /**
+ * The content model of element.
+ */
+ public void setAsCM(ASContentModel asCM);
+
+ /**
+ * TheASNamedObjectMap containing
+ * ASAttributeDeclarations for all the attributes that can
+ * appear on this type of element.
+ */
+ public ASNamedObjectMap getASAttributeDecls();
+ /**
+ * TheASNamedObjectMap containing
+ * ASAttributeDeclarations for all the attributes that can
+ * appear on this type of element.
+ */
+ public void setASAttributeDecls(ASNamedObjectMap ASAttributeDecls);
+
+ /**
+ * Adds an ASAttributeDeclaration for the element being
+ * declared.
+ * @param attributeDecl The new attribute to add. If the attribute
+ * declaration already exists for the element, the call does not have
+ * any effect.
+ */
+ public void addASAttributeDecl(ASAttributeDeclaration attributeDecl);
+
+ /**
+ * Removes an ASAttributeDeclaration from the element being
+ * declared.
+ * @param attributeDecl The attribute declaraition to be removed. If the
+ * attribute declaration does not exist for the element, the call does
+ * not have any effect.
+ * @return null if the attribute does not exist. Otherwise
+ * returns the attribute being removed.
+ */
+ public ASAttributeDeclaration removeASAttributeDecl(ASAttributeDeclaration attributeDecl);
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASEntityDeclaration.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASEntityDeclaration.java
new file mode 100644
index 0000000..963b351
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASEntityDeclaration.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+/**
+ * @deprecated
+ * Models a general entity declaration in an abstract schema. The abstract
+ * schema does not handle any parameter entity. It is assumed that the
+ * parameter entities are expanded by the implementation as the abstract
+ * schema is built.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface ASEntityDeclaration extends ASObject {
+ // EntityType
+ /**
+ * constant defining an internal entity.
+ */
+ public static final short INTERNAL_ENTITY = 1;
+ /**
+ * constant defining an external entity.
+ */
+ public static final short EXTERNAL_ENTITY = 2;
+
+ /**
+ * The type of the entity as defined above.
+ */
+ public short getEntityType();
+ /**
+ * The type of the entity as defined above.
+ */
+ public void setEntityType(short entityType);
+
+ /**
+ * The replacement text for the internal entity. The entity references
+ * within the replacement text are kept intact. For an entity of type
+ * EXTERNAL_ENTITY , this is null .
+ */
+ public String getEntityValue();
+ /**
+ * The replacement text for the internal entity. The entity references
+ * within the replacement text are kept intact. For an entity of type
+ * EXTERNAL_ENTITY , this is null .
+ */
+ public void setEntityValue(String entityValue);
+
+ /**
+ * the URI reference representing the system identifier for the notation
+ * declaration, if present, null otherwise.
+ */
+ public String getSystemId();
+ /**
+ * the URI reference representing the system identifier for the notation
+ * declaration, if present, null otherwise.
+ */
+ public void setSystemId(String systemId);
+
+ /**
+ * The string representing the public identifier for this notation
+ * declaration, if present; null otherwise.
+ */
+ public String getPublicId();
+ /**
+ * The string representing the public identifier for this notation
+ * declaration, if present; null otherwise.
+ */
+ public void setPublicId(String publicId);
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASModel.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASModel.java
new file mode 100644
index 0000000..e4da759
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASModel.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+import org.w3c.dom.DOMException;
+
+/**
+ * @deprecated
+ * To begin with, an abstract schema is a generic structure that could
+ * contain both internal and external subsets. An ASModel is an
+ * abstract object that could map to a DTD , an XML Schema , a database
+ * schema, etc. An ASModel could represent either an internal
+ * or an external subset; hence an abstract schema could be composed of an
+ * ASModel representing the internal subset and an
+ * ASModel representing the external subset. Note that the
+ * ASModel representing the external subset could consult the
+ * ASModel representing the internal subset. Furthermore, the
+ * ASModel representing the internal subset could be set to
+ * null by the setInternalAS method as a mechanism for
+ * "removal". In addition, only one ASModel representing the
+ * external subset can be specified as "active" and it is possible that none
+ * are "active". Finally, the ASModel contains the factory
+ * methods needed to create a various types of ASObjects like
+ * ASElementDeclaration , ASAttributeDeclaration ,
+ * etc.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface ASModel extends ASObject {
+ /**
+ * true if this ASModel defines the document
+ * structure in terms of namespaces and local names ; false
+ * if the document structure is defined only in terms of
+ * QNames .
+ */
+ public boolean getIsNamespaceAware();
+
+ /**
+ * 0 if used internally, 1 if used externally, 2 if not all. An exception
+ * will be raised if it is incompatibly shared or in use as an internal
+ * subset.
+ */
+ public short getUsageLocation();
+
+ /**
+ * The URI reference.
+ */
+ public String getAsLocation();
+ /**
+ * The URI reference.
+ */
+ public void setAsLocation(String asLocation);
+
+ /**
+ * The hint to locating an ASModel.
+ */
+ public String getAsHint();
+ /**
+ * The hint to locating an ASModel.
+ */
+ public void setAsHint(String asHint);
+
+ /**
+ * Instead of returning an all-in-one ASObject with
+ * ASModel methods, have discernible top-level/"global"
+ * element declarations. If one attempts to add, set, or remove a node
+ * type other than the intended one, a hierarchy exception (or
+ * equivalent is thrown).
+ */
+ public ASNamedObjectMap getElementDeclarations();
+
+ /**
+ * Instead of returning an all-in-one ASObject with
+ * ASModel methods, have discernible top-level/"global"
+ * attribute declarations. If one attempts to add, set, or remove a node
+ * type other than the intended one, a hierarchy exception (or
+ * equivalent is thrown).
+ */
+ public ASNamedObjectMap getAttributeDeclarations();
+
+ /**
+ * Instead of returning an all-in-one ASObject with
+ * ASModel methods, have discernible top-level/"global"
+ * notation declarations. If one attempts to add, set, or remove a node
+ * type other than the intended one, a hierarchy exception (or
+ * equivalent is thrown).
+ */
+ public ASNamedObjectMap getNotationDeclarations();
+
+ /**
+ * Instead of returning an all-in-one ASObject with
+ * ASModel methods, have discernible top-level/"global"
+ * entity declarations. If one attempts to add, set, or remove a node
+ * type other than the intended one, a hierarchy exception (or
+ * equivalent is thrown).
+ */
+ public ASNamedObjectMap getEntityDeclarations();
+
+ /**
+ * Instead of returning an all-in-one ASObject with
+ * ASModel methods, have discernible top-level/"global
+ * content model declarations. If one attempts to add, set, or remove a
+ * node type other than the intended one, a hierarchy exception (or
+ * equivalent is thrown).
+ */
+ public ASNamedObjectMap getContentModelDeclarations();
+
+ /**
+ * This method will allow the nesting or "importation" of ASModels.
+ * @param abstractSchema ASModel to be set. Subsequent calls will nest
+ * the ASModels within the specified ownerASModel .
+ */
+ public void addASModel(ASModel abstractSchema);
+
+ /**
+ * To retrieve a list of nested ASModels without reference to names.
+ * @return A list of ASModels.
+ */
+ public ASObjectList getASModels();
+
+ /**
+ * Removes only the specified ASModel from the list of
+ * ASModel s.
+ * @param as AS to be removed.
+ */
+ public void removeAS(ASModel as);
+
+ /**
+ * Determines if an ASModel itself is valid, i.e., confirming
+ * that it's well-formed and valid per its own formal grammar.
+ * @return true if the ASModel is valid,
+ * false otherwise.
+ */
+ public boolean validate();
+
+ /**
+ * Creates an element declaration for the element type specified.
+ * @param namespaceURI The namespace URI of the element type
+ * being declared.
+ * @param name The name of the element. The format of the name could be
+ * an NCName as defined by XML Namespaces or a Name as defined by XML
+ * 1.0; it's ASModel-dependent.
+ * @return A new ASElementDeclaration object with
+ * name attribute set to tagname and
+ * namespaceURI set to systemId . Other
+ * attributes of the element declaration are set through
+ * ASElementDeclaration interface methods.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * illegal character.
+ */
+ public ASElementDeclaration createASElementDeclaration(String namespaceURI,
+ String name)
+ throws DOMException;
+
+ /**
+ * Creates an attribute declaration.
+ * @param namespaceURI The namespace URI of the attribute being declared.
+ * @param name The name of the attribute. The format of the name could be
+ * an NCName as defined by XML Namespaces or a Name as defined by XML
+ * 1.0; it's ASModel-dependent.
+ * @return A new ASAttributeDeclaration object with
+ * appropriate attributes set by input parameters.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the input name
+ * parameter contains an illegal character.
+ */
+ public ASAttributeDeclaration createASAttributeDeclaration(String namespaceURI,
+ String name)
+ throws DOMException;
+
+ /**
+ * Creates a new notation declaration.
+ * @param namespaceURI The namespace URI of the notation being declared.
+ * @param name The name of the notation. The format of the name could be
+ * an NCName as defined by XML Namespaces or a Name as defined by XML
+ * 1.0; it's ASModel-dependent.
+ * @param systemId The system identifier for the notation declaration.
+ * @param publicId The public identifier for the notation declaration.
+ * @return A new ASNotationDeclaration object with
+ * notationName attribute set to name and
+ * publicId and systemId set to the
+ * corresponding fields.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * illegal character.
+ */
+ public ASNotationDeclaration createASNotationDeclaration(String namespaceURI,
+ String name,
+ String systemId,
+ String publicId)
+ throws DOMException;
+
+ /**
+ * Creates an ASEntityDeclaration.
+ * @param name The name of the entity being declared.
+ * @return A new ASEntityDeclaration object with
+ * entityName attribute set to name.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * illegal character.
+ */
+ public ASEntityDeclaration createASEntityDeclaration(String name)
+ throws DOMException;
+
+ /**
+ * Creates an object which describes part of an
+ * ASElementDeclaration 's content model.
+ * @param minOccurs The minimum occurrence for the subModels of this
+ * ASContentModel .
+ * @param maxOccurs The maximum occurrence for the subModels of this
+ * ASContentModel .
+ * @param operator operator of type AS_CHOICE ,
+ * AS_SEQUENCE , AS_ALL or
+ * AS_NONE .
+ * @return A new ASContentModel object.
+ * @exception DOMASException
+ * A DOMASException, e.g., minOccurs > maxOccurs .
+ */
+ public ASContentModel createASContentModel(int minOccurs,
+ int maxOccurs,
+ short operator)
+ throws DOMASException;
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASNamedObjectMap.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASNamedObjectMap.java
new file mode 100644
index 0000000..2bf706e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASNamedObjectMap.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+import org.w3c.dom.DOMException;
+
+/**
+ * @deprecated
+ * Objects implementing the ASNamedObjectMap interface are used
+ * to represent collections of abstract schema nodes that can be accessed by
+ * name. Note that ASNamedObjectMap does not inherit from
+ * ASObjectList ; ASNamedObjectMaps are not
+ * maintained in any particular order. Objects contained in an object
+ * implementing ASNamedObjectMap may also be accessed by an
+ * ordinal index, but this is simply to allow convenient enumeration of the
+ * contents of a ASNamedObjectMap , and does not imply that the
+ * DOM specifies an order to these ASObjects .
+ * ASNamedObjectMap object in the DOM are live.
+ *
See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface ASNamedObjectMap {
+ /**
+ * The number of ASObjects in the ASObjectList .
+ * The range of valid child node indices is 0 to length-1
+ * inclusive.
+ */
+ public int getLength();
+
+ /**
+ * Retrieves an ASObject specified by name.
+ * @param name The nodeName of an ASObject to
+ * retrieve.
+ * @return An ASObject with specified node name and
+ * null if the map does not contain an element with the
+ * given name.
+ */
+ public ASObject getNamedItem(String name);
+
+ /**
+ * Retrieves an ASObject specified by local name and
+ * namespace URI.
+ * @param namespaceURI The namespace URI of the ASObject to
+ * retrieve.
+ * @param localName The local name of the ASObject to
+ * retrieve.
+ * @return A ASObject (of any type) with the specified local
+ * name and namespace URI, or null if they do not
+ * identify any ASObject in this map.
+ */
+ public ASObject getNamedItemNS(String namespaceURI,
+ String localName);
+
+ /**
+ * Returns the index th item in the map. The index starts at
+ * 0 . If index is greater than or equal to the
+ * number of nodes in the list, this returns null .
+ * @param index The position in the map from which the item is to be
+ * retrieved.
+ * @return The ASObject at the index th position
+ * in the ASNamedObjectMap , or null if that
+ * is not a valid index.
+ */
+ public ASObject item(int index);
+
+ /**
+ * Removes an ASObject specified by a nodeName .
+ * @param name The nodeName of the ASObject to
+ * be removed.
+ * @return The ASObject removed from this map if an
+ * ASObject with such a name exists.
+ * @exception DOMException
+ * NOT_FOUND_ERR: Raised if there is no node named name in
+ * this map.
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
+ */
+ public ASObject removeNamedItem(String name)
+ throws DOMException;
+
+ /**
+ * Removes an ASObject specified by a namespace URI and a
+ * local name.
+ * @param namespaceURI The namespace URI of the ASObject to
+ * be removed.
+ * @param localName The local name of the ASObject to remove.
+ * @return The ASObject removed from this map if an
+ * ASObject with such a local name and namespace URI
+ * exists.
+ * @exception DOMException
+ * NOT_FOUND_ERR: Raised if there is no node with the specified
+ * namespaceURI and localName in this map.
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
+ */
+ public ASObject removeNamedItemNS(String namespaceURI,
+ String localName)
+ throws DOMException;
+
+ /**
+ * Adds an ASObject using its nodeName
+ * attribute. If an ASObject with that name is already
+ * present in this map, it is replaced by the new one.
+ * @param newASObject The ASObject to be inserted in the map
+ * with its nodeName as the key.
+ * @return If the new node replaces an existing one, the replaced node is
+ * returned, otherwise null .
+ * @exception DOMException
+ * WRONG_DOCUMENT_ERR: Raised if arg was created from a
+ * different ASModel than the one that created this map.
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
+ * HIERARCHY_REQUEST_ERR: Raised if an attempt is made to add a node
+ * doesn't belong in this ASNamedObjectMap .
+ */
+ public ASObject setNamedItem(ASObject newASObject)
+ throws DOMException;
+
+ /**
+ * Adds an ASObject using its namespaceURI and
+ * localName . If an ASObject with the same
+ * namespaceURI and localName is already
+ * present in this map, it is replaced by the new one.
+ * @param newASObject The ASObject to be inserted in the
+ * map.The ASObject will later be accessible using the
+ * value of its namespaceURI and localName
+ * attributes.
+ * @return If the new node replaces an existing one, the replaced node is
+ * returned, otherwise null .
+ * @exception DOMException
+ * WRONG_DOCUMENT_ERR : Raised if arg was
+ * created from a different ASModel than the one that
+ * created this map.
+ *
NO_MODIFICATION_ALLOWED_ERR : Raised if this map is
+ * readonly.
+ *
HIERARCHY_REQUEST_ERR : Raised if an attempt is made
+ * to add a node doesn't belong in this ASNamedObjectMap .
+ */
+ public ASObject setNamedItemNS(ASObject newASObject)
+ throws DOMException;
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASNotationDeclaration.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASNotationDeclaration.java
new file mode 100644
index 0000000..f971e05
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASNotationDeclaration.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+/**
+ * @deprecated
+ * This interface represents a notation declaration.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface ASNotationDeclaration extends ASObject {
+ /**
+ * the URI reference representing the system identifier for the notation
+ * declaration, if present, null otherwise.
+ */
+ public String getSystemId();
+ /**
+ * the URI reference representing the system identifier for the notation
+ * declaration, if present, null otherwise.
+ */
+ public void setSystemId(String systemId);
+
+ /**
+ * The string representing the public identifier for this notation
+ * declaration, if present; null otherwise.
+ */
+ public String getPublicId();
+ /**
+ * The string representing the public identifier for this notation
+ * declaration, if present; null otherwise.
+ */
+ public void setPublicId(String publicId);
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASObject.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASObject.java
new file mode 100644
index 0000000..ce125c4
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASObject.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+/**
+ * @deprecated
+ * The ASObject interface is analogous to a Node in
+ * , e.g., an element declaration.
+ * Opaque.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface ASObject {
+ // ASObjectType
+ /**
+ * The node is an ASElementDeclaration .
+ */
+ public static final short AS_ELEMENT_DECLARATION = 1;
+ /**
+ * The node is an ASAttributeDeclaration .
+ */
+ public static final short AS_ATTRIBUTE_DECLARATION = 2;
+ /**
+ * The node is a ASNotationDeclaration .
+ */
+ public static final short AS_NOTATION_DECLARATION = 3;
+ /**
+ * The node is an ASEntityDeclaration .
+ */
+ public static final short AS_ENTITY_DECLARATION = 4;
+ /**
+ * The node is a ASContentModel .
+ */
+ public static final short AS_CONTENTMODEL = 5;
+ /**
+ * The node is a ASModel .
+ */
+ public static final short AS_MODEL = 6;
+
+ /**
+ * A code representing the underlying object as defined above.
+ */
+ public short getAsNodeType();
+
+ /**
+ * The ASModel object associated with this
+ * ASObject . For a node of type AS_MODEL , this
+ * is null .
+ */
+ public ASModel getOwnerASModel();
+ /**
+ * The ASModel object associated with this
+ * ASObject . For a node of type AS_MODEL , this
+ * is null .
+ */
+ public void setOwnerASModel(ASModel ownerASModel);
+
+ /**
+ * The name of this ASObject depending on the
+ * ASObject type.
+ */
+ public String getNodeName();
+ /**
+ * The name of this ASObject depending on the
+ * ASObject type.
+ */
+ public void setNodeName(String nodeName);
+
+ /**
+ * The namespace prefix of this node, or null if it is
+ * unspecified.
+ */
+ public String getPrefix();
+ /**
+ * The namespace prefix of this node, or null if it is
+ * unspecified.
+ */
+ public void setPrefix(String prefix);
+
+ /**
+ * Returns the local part of the qualified name of this
+ * ASObject .
+ */
+ public String getLocalName();
+ /**
+ * Returns the local part of the qualified name of this
+ * ASObject .
+ */
+ public void setLocalName(String localName);
+
+ /**
+ * The namespace URI of this node, or null if it is
+ * unspecified. defines how a namespace URI is attached to schema
+ * components.
+ */
+ public String getNamespaceURI();
+ /**
+ * The namespace URI of this node, or null if it is
+ * unspecified. defines how a namespace URI is attached to schema
+ * components.
+ */
+ public void setNamespaceURI(String namespaceURI);
+
+ /**
+ * Creates a copy of this ASObject . See text for
+ * cloneNode off of Node but substitute AS
+ * functionality.
+ * @param deep Setting the deep flag on, causes the whole
+ * subtree to be duplicated. Setting it to false only
+ * duplicates its immediate child nodes.
+ * @return Cloned ASObject .
+ */
+ public ASObject cloneASObject(boolean deep);
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASObjectList.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASObjectList.java
new file mode 100644
index 0000000..111f6e2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ASObjectList.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+/**
+ * @deprecated
+ * The ASObjectList interface provides the abstraction of an
+ * ordered collection of AS nodes, without defining or constraining how this
+ * collection is implemented. ASObjectList objects in the DOM
+ * AS are live.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface ASObjectList {
+ /**
+ * The number of ASObjects in the list. The range of valid
+ * child node indices is 0 to length-1 inclusive.
+ */
+ public int getLength();
+
+ /**
+ * Returns the index th item in the collection. The index
+ * starts at 0. If index is greater than or equal to the
+ * number of nodes in the list, this returns null .
+ * @param index index into the collection.
+ * @return The ASObject at the index th position
+ * in the ASObjectList , or null if that is
+ * not a valid index.
+ */
+ public ASObject item(int index);
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/CharacterDataEditAS.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/CharacterDataEditAS.java
new file mode 100644
index 0000000..02c3af5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/CharacterDataEditAS.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+/**
+ * @deprecated
+ * This interface extends the NodeEditAS interface with
+ * additional methods for document editing. An object implementing this
+ * interface must also implement NodeEditAS interface.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface CharacterDataEditAS extends NodeEditAS {
+ /**
+ * true if content only whitespace; false for
+ * non-whitespace.
+ */
+ public boolean getIsWhitespaceOnly();
+
+ /**
+ * Determines if data can be set.
+ * @param offset Offset.
+ * @param count Argument to be set.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canSetData(int offset,
+ int count);
+
+ /**
+ * Determines if data can be appended.
+ * @param arg Argument to be appended.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canAppendData(String arg);
+
+ /**
+ * Determines if data can be replaced.
+ * @param offset Offset.
+ * @param count Replacement.
+ * @param arg Argument to be set.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canReplaceData(int offset,
+ int count,
+ String arg);
+
+ /**
+ * Determines if data can be inserted.
+ * @param offset Offset.
+ * @param arg Argument to be set.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canInsertData(int offset,
+ String arg);
+
+ /**
+ * Determines if data can be deleted.
+ * @param offset Offset.
+ * @param count Number of 16-bit units to delete.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canDeleteData(int offset,
+ int count);
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/DOMASBuilder.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/DOMASBuilder.java
new file mode 100644
index 0000000..d7a620b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/DOMASBuilder.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSParser;
+
+/**
+ * @deprecated
+ * An Abstract Schema parser interface.
+ * DOMASBuilder provides an API for parsing Abstract Schemas
+ * and building the corresponding ASModel tree.
+ *
See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface DOMASBuilder extends LSParser {
+ /**
+ * Associate an ASModel with a LSParser . This
+ * ASModel will be used by the "
+ * validate-if-schema " and "
+ * datatype-normalization " options during the load of a new
+ * Document .
+ */
+ public ASModel getAbstractSchema();
+ /**
+ * Associate an ASModel with a LSParser . This
+ * ASModel will be used by the "
+ * validate-if-schema " and "
+ * datatype-normalization " options during the load of a new
+ * Document .
+ */
+ public void setAbstractSchema(ASModel abstractSchema);
+
+ /**
+ * Parse a Abstract Schema from a location identified by an URI reference.
+ * @param uri The location of the Abstract Schema to be read.
+ * @return The newly created Abstract Schema.
+ * @exception DOMASException
+ * Exceptions raised by parseASURI() originate with the
+ * installed ErrorHandler, and thus depend on the implementation of
+ * the DOMErrorHandler interfaces. The default error
+ * handlers will raise a DOMASException if any form of
+ * Abstract Schema inconsistencies or warning occurs during the parse,
+ * but application defined errorHandlers are not required to do so.
+ * WRONG_MIME_TYPE_ERR: Raised when mimeTypeCheck is
+ * true and the input source has an incorrect MIME Type.
+ * See the attribute mimeTypeCheck .
+ * @exception DOMSystemException
+ * Exceptions raised by parseURI() originate with the
+ * installed ErrorHandler, and thus depend on the implementation of
+ * the DOMErrorHandler interfaces. The default error
+ * handlers will raise a DOMSystemException if any form I/O or other
+ * system error occurs during the parse, but application defined error
+ * handlers are not required to do so.
+ */
+ public ASModel parseASURI(String uri)
+ throws DOMASException, Exception;
+
+ /**
+ * Parse a Abstract Schema from a location identified by an
+ * LSInput .
+ * @param is The LSInput from which the source
+ * Abstract Schema is to be read.
+ * @return The newly created ASModel .
+ * @exception DOMASException
+ * Exceptions raised by parseASURI() originate with the
+ * installed ErrorHandler, and thus depend on the implementation of
+ * the DOMErrorHandler interfaces. The default error
+ * handlers will raise a DOMASException if any form of
+ * Abstract Schema inconsistencies or warning occurs during the parse,
+ * but application defined errorHandlers are not required to do so.
+ * Raise a WRONG_MIME_TYPE_ERR when mimeTypeCheck is
+ * true and the inputsource has an incorrect MIME Type.
+ * See attribute mimeTypeCheck .
+ * @exception DOMSystemException
+ * Exceptions raised by parseURI() originate with the
+ * installed ErrorHandler, and thus depend on the implementation of
+ * the DOMErrorHandler interfaces. The default error
+ * handlers will raise a DOMSystemException if any form I/O or other
+ * system error occurs during the parse, but application defined error
+ * handlers are not required to do so.
+ */
+ public ASModel parseASInputSource(LSInput is)
+ throws DOMASException, Exception;
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/DOMASException.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/DOMASException.java
new file mode 100644
index 0000000..42033ac
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/DOMASException.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+/**
+ * @deprecated
+ * Abstract Schemas operations may throw a DOMSystemException as
+ * described in their descriptions.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public class DOMASException extends RuntimeException {
+ public DOMASException(short code, String message) {
+ super(message);
+ this.code = code;
+ }
+ public short code;
+ // ASExceptionCode
+ /**
+ * If an element declaration already exists with the same name within an
+ * AS_CHOICE operator.
+ */
+ public static final short DUPLICATE_NAME_ERR = 1;
+ /**
+ * If the type of the ASObject is neither an
+ * ASContentModel nor an ASElementDeclaration .
+ */
+ public static final short TYPE_ERR = 2;
+ /**
+ * If the DocumentEditAS related to the node does not have
+ * any active ASModel and wfValidityCheckLevel
+ * is set to PARTIAL or STRICT_VALIDITY_CHECK .
+ */
+ public static final short NO_AS_AVAILABLE = 3;
+ /**
+ * When mimeTypeCheck is true and the input
+ * source has an incorrect MIME Type. See the attribute
+ * mimeTypeCheck .
+ */
+ public static final short WRONG_MIME_TYPE_ERR = 4;
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/DOMASWriter.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/DOMASWriter.java
new file mode 100644
index 0000000..4dafbb6
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/DOMASWriter.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+import org.w3c.dom.ls.LSSerializer;
+
+/**
+ * @deprecated
+ * A Abstract Schema serialization interface.
+ * DOMASWriters provides an API for serializing Abstract Schemas out in
+ * the form of a source Abstract Schema. The Abstract Schema is written to
+ * an output stream, the type of which depends on the specific language
+ * bindings in use.
+ * DOMASWriter is a generic Abstract Schema serialization interface. It
+ * can be applied to both an internal Abstract Schema and/or an external
+ * Abstract Schema. DOMASWriter is applied to serialize a single Abstract
+ * Schema. Serializing a document with an active Internal Abstract Schema
+ * will serialize this internal Abstract Schema with the document as it is
+ * part of the Document (see LSSerializer ).
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface DOMASWriter extends LSSerializer {
+ /**
+ * Write out the specified Abstract Schema to the specified destination.
+ * Does it write a DTD or an XML Schema (or something else)? Is it
+ * possible to use this method to convert a DTD to an XML Schema?
+ * @param destination The destination for the data to be written.
+ * @param model The Abstract Schema to serialize.
+ * @exception DOMSystemException
+ * This exception will be raised in response to any sort of IO or system
+ * error that occurs while writing to the destination. It may wrap an
+ * underlying system exception.
+ */
+ public void writeASModel(java.io.OutputStream destination,
+ ASModel model)
+ throws Exception;
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/DOMImplementationAS.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/DOMImplementationAS.java
new file mode 100644
index 0000000..30baa90
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/DOMImplementationAS.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+/**
+ * @deprecated
+ * This interface allows creation of an ASModel . The expectation
+ * is that an instance of the DOMImplementationAS interface can
+ * be obtained by using binding-specific casting methods on an instance of
+ * the DOMImplementation interface when the DOM implementation
+ * supports the feature "AS-EDIT ".
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface DOMImplementationAS {
+ /**
+ * Creates an ASModel.
+ * @param isNamespaceAware Allow creation of ASModel with
+ * this attribute set to a specific value.
+ * @return A null return indicates failure.what is a
+ * failure? Could be a system error.
+ */
+ public ASModel createAS(boolean isNamespaceAware);
+
+ /**
+ * Creates an DOMASBuilder .Do we need the method since we
+ * already have DOMImplementationLS.createDOMParser ?
+ * @return a DOMASBuilder
+ */
+ public DOMASBuilder createDOMASBuilder();
+
+ /**
+ * Creates an DOMASWriter .
+ * @return a DOMASWriter
+ */
+ public DOMASWriter createDOMASWriter();
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/DocumentAS.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/DocumentAS.java
new file mode 100644
index 0000000..4ed13e6
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/DocumentAS.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+import org.w3c.dom.DOMException;
+
+/**
+ * @deprecated
+ * This interface extends the Document interface with additional
+ * methods for both document and AS editing.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface DocumentAS {
+ /**
+ * The active external ASModel. Note that the active external
+ * ASModel is responsible for consulting the internal
+ * ASModel, so if an attribute is declared in the internal
+ * ASModel and the corresponding ownerElements
+ * points to a ASElementDeclaration s defined in the active
+ * external ASModel, changing the active external ASModel will cause the
+ * ownerElements to be recomputed. If the
+ * ownerElements is not defined in the newly active
+ * external ASModel, the ownerElements will be an empty
+ * node list.
+ */
+ public ASModel getActiveASModel();
+ /**
+ * The active external ASModel. Note that the active external
+ * ASModel is responsible for consulting the internal
+ * ASModel, so if an attribute is declared in the internal
+ * ASModel and the corresponding ownerElements
+ * points to a ASElementDeclaration s defined in the active
+ * external ASModel, changing the active external ASModel will cause the
+ * ownerElements to be recomputed. If the
+ * ownerElements is not defined in the newly active
+ * external ASModel, the ownerElements will be an empty
+ * node list.
+ */
+ public void setActiveASModel(ASModel activeASModel);
+
+ /**
+ * A list of ASObject s of type AS_MODEL s
+ * associated with a document. The addAS method associates
+ * a ASModel with a document.
+ */
+ public ASObjectList getBoundASModels();
+ /**
+ * A list of ASObject s of type AS_MODEL s
+ * associated with a document. The addAS method associates
+ * a ASModel with a document.
+ */
+ public void setBoundASModels(ASObjectList boundASModels);
+
+ /**
+ * Retrieve the internal ASModel of a document.
+ * @return ASModel .
+ */
+ public ASModel getInternalAS();
+
+ /**
+ * Sets the internal subset ASModel of a document. This could
+ * be null as a mechanism for "removal".
+ * @param as ASModel to be the internal subset of the
+ * document.
+ */
+ public void setInternalAS(ASModel as);
+
+ /**
+ * Associate a ASModel with a document. Can be invoked
+ * multiple times to result in a list of ASModel s. Note
+ * that only one internal ASModel is associated with the
+ * document, however, and that only one of the possible list of
+ * ASModel s is active at any one time.
+ * @param as ASModel to be associated with the document.
+ */
+ public void addAS(ASModel as);
+
+ /**
+ * Removes a ASModel associated with a document. Can be
+ * invoked multiple times to remove a number of these in the list of
+ * ASModel s.
+ * @param as The ASModel to be removed.
+ */
+ public void removeAS(ASModel as);
+
+ /**
+ * Gets the AS editing object describing this elementThis method needs to
+ * be changed and others added.
+ * @return ASElementDeclaration object if the implementation supports "
+ * AS-EDIT " feature. Otherwise null .
+ * @exception DOMException
+ * NOT_FOUND_ERR: Raised if no ASModel is present.
+ */
+ public ASElementDeclaration getElementDeclaration()
+ throws DOMException;
+
+ /**
+ * Validates the document against the ASModel .
+ * @exception DOMASException
+ *
+ */
+ public void validate()
+ throws DOMASException;
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/DocumentEditAS.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/DocumentEditAS.java
new file mode 100644
index 0000000..27ebaef
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/DocumentEditAS.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+/**
+ * @deprecated
+ * This interface extends the NodeEditAS interface with
+ * additional methods for both document and AS editing.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface DocumentEditAS extends NodeEditAS {
+ /**
+ * An attribute specifying whether continuous checking for the validity of
+ * the document is enforced or not. Setting this to true
+ * will result in an exception being thrown, i.e.,
+ * VALIDATION_ERR , for documents that are invalid at the
+ * time of the call. If the document is invalid, then this attribute
+ * will remain false . This attribute is false
+ * by default.Add VALIDATION_ERR code to the list of constants in
+ * DOMASException.
+ */
+ public boolean getContinuousValidityChecking();
+ /**
+ * An attribute specifying whether continuous checking for the validity of
+ * the document is enforced or not. Setting this to true
+ * will result in an exception being thrown, i.e.,
+ * VALIDATION_ERR , for documents that are invalid at the
+ * time of the call. If the document is invalid, then this attribute
+ * will remain false . This attribute is false
+ * by default.Add VALIDATION_ERR code to the list of constants in
+ * DOMASException.
+ */
+ public void setContinuousValidityChecking(boolean continuousValidityChecking);
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/ElementEditAS.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ElementEditAS.java
new file mode 100644
index 0000000..c92610d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/ElementEditAS.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * @deprecated
+ * This interface extends the Element interface with additional
+ * methods for guided document editing. An object implementing this
+ * interface must also implement NodeEditAS interface.
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface ElementEditAS extends NodeEditAS {
+ /**
+ * The list of qualified element names defined in the abstract schema.
+ */
+ public NodeList getDefinedElementTypes();
+
+ /**
+ * Determines element content type.
+ * @return Constant for one of EMPTY_CONTENTTYPE, ANY_CONTENTTYPE,
+ * MIXED_CONTENTTYPE, ELEMENTS_CONTENTTYPE.
+ */
+ public short contentType();
+
+ /**
+ * Determines if the value for specified attribute can be set.
+ * @param attrname Name of attribute.
+ * @param attrval Value to be assigned to the attribute.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canSetAttribute(String attrname,
+ String attrval);
+
+ /**
+ * Determines if an attribute node can be added with respect to the
+ * validity check level.This is an attribute node, there is no need for
+ * canSetAttributreNodeNS!
+ * @param attrNode Node in which the attribute can possibly
+ * be set.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canSetAttributeNode(Attr attrNode);
+
+ /**
+ * Determines if the attribute with given namespace and qualified name can
+ * be created if not already present in the attribute list of the
+ * element. If the attribute with same qualified name and namespaceURI
+ * is already present in the elements attribute list it tests for the
+ * value of the attribute and its prefix to the new value. See DOM core
+ * setAttributeNS .
+ * @param name Qualified name of attribute.
+ * @param attrval Value to be assigned to the attribute.
+ * @param namespaceURI namespaceURI of namespace.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canSetAttributeNS(String name,
+ String attrval,
+ String namespaceURI);
+
+ /**
+ * Verifies if an attribute by the given name can be removed.
+ * @param attrname Name of attribute.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canRemoveAttribute(String attrname);
+
+ /**
+ * Verifies if an attribute by the given local name and namespace can be
+ * removed.
+ * @param attrname Local name of the attribute to be removed.
+ * @param namespaceURI The namespace URI of the attribute to remove.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canRemoveAttributeNS(String attrname,
+ String namespaceURI);
+
+ /**
+ * Determines if an attribute node can be removed.
+ * @param attrNode The Attr node to remove from the
+ * attribute list.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canRemoveAttributeNode(Node attrNode);
+
+ /**
+ * Returns an NodeList containing the possible
+ * Element names that can appear as children of this type
+ * of element.
+ * @return List of possible children element types of this element.
+ */
+ public NodeList getChildElements();
+
+ /**
+ * Returns an NodeList containing the possible
+ * Element names that can appear as a parent of this type
+ * of element.
+ * @return List of possible parent element types of this element.
+ */
+ public NodeList getParentElements();
+
+ /**
+ * Returns an NodeList containing all the possible
+ * Attr s that can appear with this type of element.
+ * @return List of possible attributes of this element.
+ */
+ public NodeList getAttributeList();
+
+ /**
+ * Determines if this element is defined in the currently active AS.
+ * @param elemTypeName Name of element.
+ * @return A boolean that is true if the element is defined,
+ * false otherwise.
+ */
+ public boolean isElementDefined(String elemTypeName);
+
+ /**
+ * Determines if this element in this namespace is defined in the
+ * currently active AS.
+ * @param elemTypeName Name of element.
+ * @param namespaceURI namespaceURI of namespace.
+ * @param name Qualified name of namespace. This is for sub-elements.
+ * @return A boolean that is true if the element is defined,
+ * false otherwise.
+ */
+ public boolean isElementDefinedNS(String elemTypeName,
+ String namespaceURI,
+ String name);
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/dom3/as/NodeEditAS.java b/resources/xerces2-j-src/org/apache/xerces/dom3/as/NodeEditAS.java
new file mode 100644
index 0000000..53953e2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/dom3/as/NodeEditAS.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2001 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.apache.xerces.dom3.as;
+
+import org.w3c.dom.Node;
+
+/**
+ * @deprecated
+ * This interface extends a Node from with additional methods
+ * for guided document editing. The expectation is that an instance of the
+ * DOMImplementationAS interface can be obtained by using
+ * binding-specific casting methods on an instance of the
+ * DOMImplementation interface when the DOM implementation
+ * supports the feature "AS-DOC ".
+ * See also the Document Object Model (DOM) Level 3 Abstract Schemas and Load
+and Save Specification.
+ */
+public interface NodeEditAS {
+ // ASCheckType
+ /**
+ * Check for well-formedness of this node.
+ */
+ public static final short WF_CHECK = 1;
+ /**
+ * Check for namespace well-formedness includes WF_CHECK .
+ */
+ public static final short NS_WF_CHECK = 2;
+ /**
+ * Checks for whether this node is partially valid. It includes
+ * NS_WF_CHECK .
+ */
+ public static final short PARTIAL_VALIDITY_CHECK = 3;
+ /**
+ * Checks for strict validity of the node with respect to active AS which
+ * by definition includes NS_WF_CHECK .
+ */
+ public static final short STRICT_VALIDITY_CHECK = 4;
+
+ /**
+ * Determines whether the insertBefore operation from the
+ * Node interface would make this document invalid with
+ * respect to the currently active AS. Describe "valid" when referring
+ * to partially completed documents.
+ * @param newChild Node to be inserted.
+ * @param refChild Reference Node .
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canInsertBefore(Node newChild,
+ Node refChild);
+
+ /**
+ * Has the same arguments as RemoveChild .
+ * @param oldChild Node to be removed.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canRemoveChild(Node oldChild);
+
+ /**
+ * Has the same arguments as ReplaceChild .
+ * @param newChild New Node .
+ * @param oldChild Node to be replaced.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canReplaceChild(Node newChild,
+ Node oldChild);
+
+ /**
+ * Has the same arguments as AppendChild .
+ * @param newChild Node to be appended.
+ * @return true if no reason it can't be done;
+ * false if it can't be done.
+ */
+ public boolean canAppendChild(Node newChild);
+
+ /**
+ * Determines if the Node is valid relative to currently active AS. It
+ * doesn't normalize before checking if the document is valid. To do so,
+ * one would need to explicitly call a normalize method.
+ * @param deep Setting the deep flag on causes the
+ * isNodeValid method to check for the whole subtree of
+ * the current node for validity. Setting it to false
+ * only checks the current node and its immediate child nodes. The
+ * validate method on the DocumentAS
+ * interface, however, checks to determine whether the entire document
+ * is valid.
+ * @param wFValidityCheckLevel Flag to tell at what level validity and
+ * well-formedness checking is done.
+ * @return true if the node is valid/well-formed in the
+ * current context and check level defined by
+ * wfValidityCheckLevel , false if not.
+ * @exception DOMASException
+ * NO_AS_AVAILABLE : Raised if the
+ * DocumentEditAS related to this node does not have any
+ * active ASModel and wfValidityCheckLevel
+ * is set to PARTIAL or STRICT_VALIDITY_CHECK
+ * .
+ */
+ public boolean isNodeValid(boolean deep,
+ short wFValidityCheckLevel)
+ throws DOMASException;
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/Constants.java b/resources/xerces2-j-src/org/apache/xerces/impl/Constants.java
new file mode 100644
index 0000000..2b4fb3e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/Constants.java
@@ -0,0 +1,696 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+/**
+ * Commonly used constants.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ *
+ * @version $Id$
+ */
+public final class Constants {
+
+ //
+ // Constants
+ //
+ // Schema Types:
+ public static final String NS_XMLSCHEMA = "http://www.w3.org/2001/XMLSchema".intern();
+ public static final String NS_DTD = "http://www.w3.org/TR/REC-xml".intern();
+
+ // Schema Versions:
+ public static final String W3C_XML_SCHEMA10_NS_URI = "http://www.w3.org/XML/XMLSchema/v1.0".intern();
+
+ // sax features
+
+ /** SAX feature prefix ("http://xml.org/sax/features/"). */
+ public static final String SAX_FEATURE_PREFIX = "http://xml.org/sax/features/";
+
+ /** Namespaces feature ("namespaces"). */
+ public static final String NAMESPACES_FEATURE = "namespaces";
+
+ /** Namespace prefixes feature ("namespace-prefixes"). */
+ public static final String NAMESPACE_PREFIXES_FEATURE = "namespace-prefixes";
+
+ /** String interning feature ("string-interning"). */
+ public static final String STRING_INTERNING_FEATURE = "string-interning";
+
+ /** Validation feature ("validation"). */
+ public static final String VALIDATION_FEATURE = "validation";
+
+ /** External general entities feature ("external-general-entities "). */
+ public static final String EXTERNAL_GENERAL_ENTITIES_FEATURE = "external-general-entities";
+
+ /** External parameter entities feature ("external-parameter-entities "). */
+ public static final String EXTERNAL_PARAMETER_ENTITIES_FEATURE = "external-parameter-entities";
+
+ /** Lexical handler parameter entities feature ("lexical-handler/parameter-entities"). */
+ public static final String LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE = "lexical-handler/parameter-entities";
+
+ /** Is standalone feature ("is-standalone"). */
+ public static final String IS_STANDALONE_FEATURE = "is-standalone";
+
+ /** Resolve DTD URIs feature ("resolve-dtd-uris"). */
+ public static final String RESOLVE_DTD_URIS_FEATURE = "resolve-dtd-uris";
+
+ /** Use Attributes2 feature ("use-attributes2"). */
+ public static final String USE_ATTRIBUTES2_FEATURE = "use-attributes2";
+
+ /** Use Locator2 feature ("use-locator2"). */
+ public static final String USE_LOCATOR2_FEATURE = "use-locator2";
+
+ /** Use EntityResolver2 feature ("use-entity-resolver2"). */
+ public static final String USE_ENTITY_RESOLVER2_FEATURE = "use-entity-resolver2";
+
+ /** Unicode normalization checking feature ("unicode-normalization-checking"). */
+ public static final String UNICODE_NORMALIZATION_CHECKING_FEATURE = "unicode-normalization-checking";
+
+ /** xmlns URIs feature ("xmlns-uris"). */
+ public static final String XMLNS_URIS_FEATURE = "xmlns-uris";
+
+ /** XML 1.1 feature ("xml-1.1"). */
+ public static final String XML_11_FEATURE = "xml-1.1";
+
+ /** Allow unparsed entity and notation declaration events to be sent after the end DTD event ("allow-dtd-events-after-endDTD") */
+ public static final String ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE = "allow-dtd-events-after-endDTD";
+
+ // sax properties
+
+ /** SAX property prefix ("http://xml.org/sax/properties/"). */
+ public static final String SAX_PROPERTY_PREFIX = "http://xml.org/sax/properties/";
+
+ /** Declaration handler property ("declaration-handler"). */
+ public static final String DECLARATION_HANDLER_PROPERTY = "declaration-handler";
+
+ /** Lexical handler property ("lexical-handler"). */
+ public static final String LEXICAL_HANDLER_PROPERTY = "lexical-handler";
+
+ /** DOM node property ("dom-node"). */
+ public static final String DOM_NODE_PROPERTY = "dom-node";
+
+ /** XML string property ("xml-string"). */
+ public static final String XML_STRING_PROPERTY = "xml-string";
+
+ /** Document XML version property ("document-xml-version"). */
+ public static final String DOCUMENT_XML_VERSION_PROPERTY = "document-xml-version";
+
+
+ //
+ // JAXP properties
+ //
+
+ /** JAXP property prefix ("http://java.sun.com/xml/jaxp/properties/"). */
+ public static final String JAXP_PROPERTY_PREFIX =
+ "http://java.sun.com/xml/jaxp/properties/";
+
+ /** JAXP schemaSource property: when used internally may include DTD sources (DOM) */
+ public static final String SCHEMA_SOURCE = "schemaSource";
+
+ /** JAXP schemaSource language: when used internally may include DTD namespace (DOM) */
+ public static final String SCHEMA_LANGUAGE = "schemaLanguage";
+
+
+ //
+ // DOM features
+ //
+
+ /** Comments feature ("include-comments"). */
+ public static final String INCLUDE_COMMENTS_FEATURE = "include-comments";
+
+ /** Create cdata nodes feature ("create-cdata-nodes"). */
+ public static final String CREATE_CDATA_NODES_FEATURE = "create-cdata-nodes";
+
+ /** Feature id: load as infoset. */
+ public static final String LOAD_AS_INFOSET = "load-as-infoset";
+
+
+ //
+ // Constants: DOM Level 3 feature ids
+ //
+
+ public static final String DOM_CANONICAL_FORM = "canonical-form";
+ public static final String DOM_CDATA_SECTIONS ="cdata-sections";
+ public static final String DOM_COMMENTS = "comments";
+
+ // REVISIT: this feature seems to have no effect for Xerces
+ public static final String DOM_CHARSET_OVERRIDES_XML_ENCODING =
+ "charset-overrides-xml-encoding";
+
+ public static final String DOM_DATATYPE_NORMALIZATION = "datatype-normalization";
+ public static final String DOM_ENTITIES = "entities";
+ public static final String DOM_INFOSET = "infoset";
+ public static final String DOM_NAMESPACES = "namespaces";
+ public static final String DOM_NAMESPACE_DECLARATIONS = "namespace-declarations";
+ public static final String DOM_SUPPORTED_MEDIATYPES_ONLY =
+ "supported-media-types-only";
+
+ public static final String DOM_VALIDATE_IF_SCHEMA = "validate-if-schema";
+ public static final String DOM_VALIDATE = "validate";
+ public static final String DOM_ELEMENT_CONTENT_WHITESPACE =
+ "element-content-whitespace";
+
+ // DOM Level 3 features defined in Core:
+ public static final String DOM_DISCARD_DEFAULT_CONTENT = "discard-default-content";
+ public static final String DOM_NORMALIZE_CHARACTERS = "normalize-characters";
+ public static final String DOM_CHECK_CHAR_NORMALIZATION = "check-character-normalization";
+ public static final String DOM_WELLFORMED = "well-formed";
+ public static final String DOM_SPLIT_CDATA = "split-cdata-sections";
+
+ // Load and Save
+ public static final String DOM_FORMAT_PRETTY_PRINT = "format-pretty-print";
+ public static final String DOM_XMLDECL = "xml-declaration";
+ public static final String DOM_UNKNOWNCHARS = "unknown-characters";
+ public static final String DOM_CERTIFIED = "certified";
+ public static final String DOM_DISALLOW_DOCTYPE = "disallow-doctype";
+ public static final String DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS = "ignore-unknown-character-denormalizations";
+
+ // DOM Properties
+ public static final String DOM_RESOURCE_RESOLVER = "resource-resolver";
+ public static final String DOM_ERROR_HANDLER = "error-handler";
+ public static final String DOM_SCHEMA_TYPE = "schema-type";
+ public static final String DOM_SCHEMA_LOCATION = "schema-location";
+
+ // XSModel
+ public static final String DOM_PSVI = "psvi";
+
+
+ // xerces features
+
+ /** Xerces features prefix ("http://apache.org/xml/features/"). */
+ public static final String XERCES_FEATURE_PREFIX = "http://apache.org/xml/features/";
+
+ /** Schema validation feature ("validation/schema"). */
+ public static final String SCHEMA_VALIDATION_FEATURE = "validation/schema";
+
+ /** Expose schema normalized values */
+ public static final String SCHEMA_NORMALIZED_VALUE = "validation/schema/normalized-value";
+
+ /** Send schema default value via characters() */
+ public static final String SCHEMA_ELEMENT_DEFAULT = "validation/schema/element-default";
+
+ /** Schema full constraint checking ("validation/schema-full-checking"). */
+ public static final String SCHEMA_FULL_CHECKING = "validation/schema-full-checking";
+
+ /** Augment Post-Schema-Validation-Infoset */
+ public static final String SCHEMA_AUGMENT_PSVI = "validation/schema/augment-psvi";
+
+ /** Dynamic validation feature ("validation/dynamic"). */
+ public static final String DYNAMIC_VALIDATION_FEATURE = "validation/dynamic";
+
+ /** Warn on duplicate attribute declaration feature ("validation/warn-on-duplicate-attdef"). */
+ public static final String WARN_ON_DUPLICATE_ATTDEF_FEATURE = "validation/warn-on-duplicate-attdef";
+
+ /** Warn on undeclared element feature ("validation/warn-on-undeclared-elemdef"). */
+ public static final String WARN_ON_UNDECLARED_ELEMDEF_FEATURE = "validation/warn-on-undeclared-elemdef";
+
+ /** Warn on duplicate entity declaration feature ("warn-on-duplicate-entitydef"). */
+ public static final String WARN_ON_DUPLICATE_ENTITYDEF_FEATURE = "warn-on-duplicate-entitydef";
+
+ /** Allow Java encoding names feature ("allow-java-encodings"). */
+ public static final String ALLOW_JAVA_ENCODINGS_FEATURE = "allow-java-encodings";
+
+ /** Disallow DOCTYPE declaration feature ("disallow-doctype-decl"). */
+ public static final String DISALLOW_DOCTYPE_DECL_FEATURE = "disallow-doctype-decl";
+
+ /** Continue after fatal error feature ("continue-after-fatal-error"). */
+ public static final String CONTINUE_AFTER_FATAL_ERROR_FEATURE = "continue-after-fatal-error";
+
+ /** Load dtd grammar when nonvalidating feature ("nonvalidating/load-dtd-grammar"). */
+ public static final String LOAD_DTD_GRAMMAR_FEATURE = "nonvalidating/load-dtd-grammar";
+
+ /** Load external dtd when nonvalidating feature ("nonvalidating/load-external-dtd"). */
+ public static final String LOAD_EXTERNAL_DTD_FEATURE = "nonvalidating/load-external-dtd";
+
+ /** Defer node expansion feature ("dom/defer-node-expansion"). */
+ public static final String DEFER_NODE_EXPANSION_FEATURE = "dom/defer-node-expansion";
+
+ /** Create entity reference nodes feature ("dom/create-entity-ref-nodes"). */
+ public static final String CREATE_ENTITY_REF_NODES_FEATURE = "dom/create-entity-ref-nodes";
+
+ /** Include ignorable whitespace feature ("dom/include-ignorable-whitespace"). */
+ public static final String INCLUDE_IGNORABLE_WHITESPACE = "dom/include-ignorable-whitespace";
+
+ /** Default attribute values feature ("validation/default-attribute-values"). */
+ public static final String DEFAULT_ATTRIBUTE_VALUES_FEATURE = "validation/default-attribute-values";
+
+ /** Validate content models feature ("validation/validate-content-models"). */
+ public static final String VALIDATE_CONTENT_MODELS_FEATURE = "validation/validate-content-models";
+
+ /** Validate datatypes feature ("validation/validate-datatypes"). */
+ public static final String VALIDATE_DATATYPES_FEATURE = "validation/validate-datatypes";
+
+ /** Balance syntax trees feature ("validation/balance-syntax-trees"). */
+ public static final String BALANCE_SYNTAX_TREES = "validation/balance-syntax-trees";
+
+ /** Notify character references feature (scanner/notify-char-refs"). */
+ public static final String NOTIFY_CHAR_REFS_FEATURE = "scanner/notify-char-refs";
+
+ /** Notify built-in (&, etc.) references feature (scanner/notify-builtin-refs"). */
+ public static final String NOTIFY_BUILTIN_REFS_FEATURE = "scanner/notify-builtin-refs";
+
+ /** Standard URI conformant feature ("standard-uri-conformant"). */
+ public static final String STANDARD_URI_CONFORMANT_FEATURE = "standard-uri-conformant";
+
+ /** Generate synthetic annotations feature ("generate-synthetic-annotations"). */
+ public static final String GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE = "generate-synthetic-annotations";
+
+ /** Validate annotations feature ("validate-annotations"). */
+ public static final String VALIDATE_ANNOTATIONS_FEATURE = "validate-annotations";
+
+ /** Honour all schemaLocations feature ("honour-all-schemaLocations"). */
+ public static final String HONOUR_ALL_SCHEMALOCATIONS_FEATURE = "honour-all-schemaLocations";
+
+ /** Namespace growth feature ("namespace-growth"). */
+ public static final String NAMESPACE_GROWTH_FEATURE = "namespace-growth";
+
+ /** Tolerate duplicates feature ("internal/tolerate-duplicates"). */
+ public static final String TOLERATE_DUPLICATES_FEATURE = "internal/tolerate-duplicates";
+
+ /** String interned feature ("internal/strings-interned"). */
+ public static final String STRINGS_INTERNED_FEATURE = "internal/strings-interned";
+
+ /** XInclude processing feature ("xinclude"). */
+ public static final String XINCLUDE_FEATURE = "xinclude";
+
+ /** XInclude fixup base URIs feature ("xinclude/fixup-base-uris"). */
+ public static final String XINCLUDE_FIXUP_BASE_URIS_FEATURE = "xinclude/fixup-base-uris";
+
+ /** XInclude fixup language feature ("xinclude/fixup-language"). */
+ public static final String XINCLUDE_FIXUP_LANGUAGE_FEATURE = "xinclude/fixup-language";
+
+ /**
+ * Feature to ignore xsi:type attributes on elements during validation,
+ * until a global element declaration is found. ("validation/schema/ignore-xsi-type-until-elemdecl")
+ * If this feature is on when validating a document, then beginning at the validation root
+ * element, xsi:type attributes are ignored until a global element declaration is
+ * found for an element. Once a global element declaration has been found, xsi:type
+ * attributes will start being processed for the sub-tree beginning at the element for
+ * which the declaration was found.
+ *
+ * Suppose an element A has two element children, B and C.
+ *
+ * If a global element declaration is found for A, xsi:type attributes on A, B and C,
+ * and all of B and C's descendents, will be processed.
+ *
+ * If no global element declaration is found for A or B, but one is found for C,
+ * then xsi:type attributes will be ignored on A and B (and any descendents of B,
+ * until a global element declaration is found), but xsi:type attributes will be
+ * processed for C and all of C's descendents.
+ *
+ * Once xsi:type attributes stop being ignored for a subtree, they do not start
+ * being ignored again, even if more elements are encountered for which no global
+ * element declaration can be found.
+ */
+ public static final String IGNORE_XSI_TYPE_FEATURE = "validation/schema/ignore-xsi-type-until-elemdecl";
+
+ /** Perform checking of ID/IDREFs ("validation/id-idref-checking") */
+ public static final String ID_IDREF_CHECKING_FEATURE = "validation/id-idref-checking";
+
+ /** Feature to ignore errors caused by identity constraints ("validation/identity-constraint-checking") */
+ public static final String IDC_CHECKING_FEATURE = "validation/identity-constraint-checking";
+
+ /** Feature to ignore errors caused by unparsed entities ("validation/unparsed-entity-checking") */
+ public static final String UNPARSED_ENTITY_CHECKING_FEATURE = "validation/unparsed-entity-checking";
+
+ /**
+ * Internal feature. When set to true the schema validator will only use
+ * schema components from the grammar pool provided.
+ */
+ public static final String USE_GRAMMAR_POOL_ONLY_FEATURE = "internal/validation/schema/use-grammar-pool-only";
+
+ /** Internal performance related feature:
+ * false - the parser settings (features/properties) have not changed between 2 parses
+ * true - the parser settings have changed between 2 parses
+ * NOTE: this feature should only be set by the parser configuration.
+ */
+ public static final String PARSER_SETTINGS = "internal/parser-settings";
+
+ // xerces properties
+
+ /** Xerces properties prefix ("http://apache.org/xml/properties/"). */
+ public static final String XERCES_PROPERTY_PREFIX = "http://apache.org/xml/properties/";
+
+ /** Current element node property ("dom/current-element-node"). */
+ public static final String CURRENT_ELEMENT_NODE_PROPERTY = "dom/current-element-node";
+
+ /** Document class name property ("dom/document-class-name"). */
+ public static final String DOCUMENT_CLASS_NAME_PROPERTY = "dom/document-class-name";
+
+ /** Symbol table property ("internal/symbol-table"). */
+ public static final String SYMBOL_TABLE_PROPERTY = "internal/symbol-table";
+
+ /** Error reporter property ("internal/error-reporter"). */
+ public static final String ERROR_REPORTER_PROPERTY = "internal/error-reporter";
+
+ /** Error handler property ("internal/error-handler"). */
+ public static final String ERROR_HANDLER_PROPERTY = "internal/error-handler";
+
+ /** XInclude handler property ("internal/xinclude-handler"). */
+ public static final String XINCLUDE_HANDLER_PROPERTY = "internal/xinclude-handler";
+
+ /** XPointer handler property ("internal/xpointer-handler"). */
+ public static final String XPOINTER_HANDLER_PROPERTY = "internal/xpointer-handler";
+
+ /** Entity manager property ("internal/entity-manager"). */
+ public static final String ENTITY_MANAGER_PROPERTY = "internal/entity-manager";
+
+ /** Input buffer size property ("input-buffer-size"). */
+ public static final String BUFFER_SIZE_PROPERTY = "input-buffer-size";
+
+ /** Security manager property ("security-manager"). */
+ public static final String SECURITY_MANAGER_PROPERTY = "security-manager";
+
+ /** Locale property ("locale"). */
+ public static final String LOCALE_PROPERTY = "locale";
+
+ /** Entity resolver property ("internal/entity-resolver"). */
+ public static final String ENTITY_RESOLVER_PROPERTY = "internal/entity-resolver";
+
+ /** Grammar pool property ("internal/grammar-pool"). */
+ public static final String XMLGRAMMAR_POOL_PROPERTY = "internal/grammar-pool";
+
+ /** Datatype validator factory ("internal/datatype-validator-factory"). */
+ public static final String DATATYPE_VALIDATOR_FACTORY_PROPERTY = "internal/datatype-validator-factory";
+
+ /** Document scanner property ("internal/document-scanner"). */
+ public static final String DOCUMENT_SCANNER_PROPERTY = "internal/document-scanner";
+
+ /** DTD scanner property ("internal/dtd-scanner"). */
+ public static final String DTD_SCANNER_PROPERTY = "internal/dtd-scanner";
+
+ /** DTD processor property ("internal/dtd-processor"). */
+ public static final String DTD_PROCESSOR_PROPERTY = "internal/dtd-processor";
+
+ /** Validator property ("internal/validator"). */
+ public static final String VALIDATOR_PROPERTY = "internal/validator";
+
+ /** Validator property ("internal/validator/dtd"). */
+ public static final String DTD_VALIDATOR_PROPERTY = "internal/validator/dtd";
+
+ /** Validator property ("internal/validator/schema"). */
+ public static final String SCHEMA_VALIDATOR_PROPERTY = "internal/validator/schema";
+
+ /** No namespace schema location property ("schema/external-schemaLocation"). */
+ public static final String SCHEMA_LOCATION = "schema/external-schemaLocation";
+
+ /** Schema location property ("schema/external-noNamespaceSchemaLocation"). */
+ public static final String SCHEMA_NONS_LOCATION = "schema/external-noNamespaceSchemaLocation";
+
+ /** Namespace binder property ("internal/namespace-binder"). */
+ public static final String NAMESPACE_BINDER_PROPERTY = "internal/namespace-binder";
+
+ /** Namespace context property ("internal/namespace-context"). */
+ public static final String NAMESPACE_CONTEXT_PROPERTY = "internal/namespace-context";
+
+ /** Validation manager property ("internal/validation-manager"). */
+ public static final String VALIDATION_MANAGER_PROPERTY = "internal/validation-manager";
+
+ /** Schema type for the root element in a document ("validation/schema/root-type-definition"). */
+ public static final String ROOT_TYPE_DEFINITION_PROPERTY = "validation/schema/root-type-definition";
+
+ /** Schema element declaration for the root element in a document ("validation/schema/root-element-declaration"). */
+ public static final String ROOT_ELEMENT_DECLARATION_PROPERTY = "validation/schema/root-element-declaration";
+
+ /** Schema element declaration for the root element in a document ("internal/validation/schema/dv-factory"). */
+ public static final String SCHEMA_DV_FACTORY_PROPERTY = "internal/validation/schema/dv-factory";
+
+ // general constants
+
+ /** Element PSVI is stored in augmentations using string "ELEMENT_PSVI" */
+ public final static String ELEMENT_PSVI = "ELEMENT_PSVI";
+
+ /** Attribute PSVI is stored in augmentations using string "ATTRIBUTE_PSVI" */
+ public final static String ATTRIBUTE_PSVI = "ATTRIBUTE_PSVI";
+
+ /**
+ * Boolean indicating whether an attribute is declared in the DTD is stored
+ * in augmentations using the string "ATTRIBUTE_DECLARED". The absence of this
+ * augmentation indicates that the attribute was not declared in the DTD.
+ */
+ public final static String ATTRIBUTE_DECLARED = "ATTRIBUTE_DECLARED";
+
+ /**
+ * Boolean indicating whether an entity referenced in the document has
+ * not been read is stored in augmentations using the string "ENTITY_SKIPPED".
+ * The absence of this augmentation indicates that the entity had a
+ * declaration and was expanded.
+ */
+ public final static String ENTITY_SKIPPED = "ENTITY_SKIPPED";
+
+ /**
+ * Boolean indicating whether a character is a probable white space
+ * character (ch <= 0x20) that was the replacement text of a character
+ * reference is stored in augmentations using the string "CHAR_REF_PROBABLE_WS".
+ * The absence of this augmentation indicates that the character is not
+ * probable white space and/or was not included from a character reference.
+ */
+ public final static String CHAR_REF_PROBABLE_WS = "CHAR_REF_PROBABLE_WS";
+
+ // XML version constants
+ public final static short XML_VERSION_ERROR = -1;
+ public final static short XML_VERSION_1_0 = 1;
+ public final static short XML_VERSION_1_1 = 2;
+
+ // Constant to enable Schema 1.1 support
+ public final static boolean SCHEMA_1_1_SUPPORT = false;
+ public final static short SCHEMA_VERSION_1_0 = 1;
+ public final static short SCHEMA_VERSION_1_0_EXTENDED = 2;
+
+ // private
+
+ /** SAX features. */
+ private static final String[] fgSAXFeatures = {
+ NAMESPACES_FEATURE,
+ NAMESPACE_PREFIXES_FEATURE,
+ STRING_INTERNING_FEATURE,
+ VALIDATION_FEATURE,
+ EXTERNAL_GENERAL_ENTITIES_FEATURE,
+ EXTERNAL_PARAMETER_ENTITIES_FEATURE,
+ };
+
+ /** SAX properties. */
+ private static final String[] fgSAXProperties = {
+ DECLARATION_HANDLER_PROPERTY,
+ LEXICAL_HANDLER_PROPERTY,
+ DOM_NODE_PROPERTY,
+ XML_STRING_PROPERTY,
+ };
+
+ /** Xerces features. */
+ private static final String[] fgXercesFeatures = {
+ SCHEMA_VALIDATION_FEATURE,
+ SCHEMA_FULL_CHECKING,
+ DYNAMIC_VALIDATION_FEATURE,
+ WARN_ON_DUPLICATE_ATTDEF_FEATURE,
+ WARN_ON_UNDECLARED_ELEMDEF_FEATURE,
+ ALLOW_JAVA_ENCODINGS_FEATURE,
+ CONTINUE_AFTER_FATAL_ERROR_FEATURE,
+ LOAD_DTD_GRAMMAR_FEATURE,
+ LOAD_EXTERNAL_DTD_FEATURE,
+ //DEFER_NODE_EXPANSION_FEATURE,
+ CREATE_ENTITY_REF_NODES_FEATURE,
+ INCLUDE_IGNORABLE_WHITESPACE,
+ //GRAMMAR_ACCESS_FEATURE,
+ DEFAULT_ATTRIBUTE_VALUES_FEATURE,
+ VALIDATE_CONTENT_MODELS_FEATURE,
+ VALIDATE_DATATYPES_FEATURE,
+ BALANCE_SYNTAX_TREES,
+ NOTIFY_CHAR_REFS_FEATURE,
+ NOTIFY_BUILTIN_REFS_FEATURE,
+ DISALLOW_DOCTYPE_DECL_FEATURE,
+ STANDARD_URI_CONFORMANT_FEATURE,
+ GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE,
+ VALIDATE_ANNOTATIONS_FEATURE,
+ HONOUR_ALL_SCHEMALOCATIONS_FEATURE,
+ XINCLUDE_FEATURE,
+ XINCLUDE_FIXUP_BASE_URIS_FEATURE,
+ XINCLUDE_FIXUP_LANGUAGE_FEATURE,
+ IGNORE_XSI_TYPE_FEATURE,
+ ID_IDREF_CHECKING_FEATURE,
+ IDC_CHECKING_FEATURE,
+ UNPARSED_ENTITY_CHECKING_FEATURE,
+ NAMESPACE_GROWTH_FEATURE,
+ TOLERATE_DUPLICATES_FEATURE,
+ STRINGS_INTERNED_FEATURE,
+ };
+
+ /** Xerces properties. */
+ private static final String[] fgXercesProperties = {
+ CURRENT_ELEMENT_NODE_PROPERTY,
+ DOCUMENT_CLASS_NAME_PROPERTY,
+ SYMBOL_TABLE_PROPERTY,
+ ERROR_HANDLER_PROPERTY,
+ ERROR_REPORTER_PROPERTY,
+ ENTITY_MANAGER_PROPERTY,
+ ENTITY_RESOLVER_PROPERTY,
+ XMLGRAMMAR_POOL_PROPERTY,
+ DATATYPE_VALIDATOR_FACTORY_PROPERTY,
+ DOCUMENT_SCANNER_PROPERTY,
+ DTD_SCANNER_PROPERTY,
+ VALIDATOR_PROPERTY,
+ SCHEMA_LOCATION,
+ SCHEMA_NONS_LOCATION,
+ VALIDATION_MANAGER_PROPERTY,
+ BUFFER_SIZE_PROPERTY,
+ SECURITY_MANAGER_PROPERTY,
+ LOCALE_PROPERTY,
+ ROOT_TYPE_DEFINITION_PROPERTY,
+ ROOT_ELEMENT_DECLARATION_PROPERTY,
+ SCHEMA_DV_FACTORY_PROPERTY,
+ };
+
+ /** Empty enumeration. */
+ private static final Enumeration fgEmptyEnumeration = new ArrayEnumeration(new Object[] {});
+
+ //
+ // Constructors
+ //
+
+ /** This class cannot be instantiated. */
+ private Constants() {}
+
+ //
+ // Public methods
+ //
+
+ // sax
+
+ /** Returns an enumeration of the SAX features. */
+ public static Enumeration getSAXFeatures() {
+ return fgSAXFeatures.length > 0
+ ? new ArrayEnumeration(fgSAXFeatures) : fgEmptyEnumeration;
+ } // getSAXFeatures():Enumeration
+
+ /** Returns an enumeration of the SAX properties. */
+ public static Enumeration getSAXProperties() {
+ return fgSAXProperties.length > 0
+ ? new ArrayEnumeration(fgSAXProperties) : fgEmptyEnumeration;
+ } // getSAXProperties():Enumeration
+
+ // xerces
+
+ /** Returns an enumeration of the Xerces features. */
+ public static Enumeration getXercesFeatures() {
+ return fgXercesFeatures.length > 0
+ ? new ArrayEnumeration(fgXercesFeatures) : fgEmptyEnumeration;
+ } // getXercesFeatures():Enumeration
+
+ /** Returns an enumeration of the Xerces properties. */
+ public static Enumeration getXercesProperties() {
+ return fgXercesProperties.length > 0
+ ? new ArrayEnumeration(fgXercesProperties) : fgEmptyEnumeration;
+ } // getXercesProperties():Enumeration
+
+ //
+ // Classes
+ //
+
+ /**
+ * An array enumeration.
+ *
+ * @author Andy Clark, IBM
+ */
+ static class ArrayEnumeration
+ implements Enumeration {
+
+ //
+ // Data
+ //
+
+ /** Array. */
+ private Object[] array;
+
+ /** Index. */
+ private int index;
+
+ //
+ // Constructors
+ //
+
+ /** Constructs an array enumeration. */
+ public ArrayEnumeration(Object[] array) {
+ this.array = array;
+ } // (Object[])
+
+ //
+ // Enumeration methods
+ //
+
+ /**
+ * Tests if this enumeration contains more elements.
+ *
+ * @return true if this enumeration contains more elements;
+ * false otherwise.
+ * @since JDK1.0
+ */
+ public boolean hasMoreElements() {
+ return index < array.length;
+ } // hasMoreElement():boolean
+
+ /**
+ * Returns the next element of this enumeration.
+ *
+ * @return the next element of this enumeration.
+ * @exception NoSuchElementException if no more elements exist.
+ * @since JDK1.0
+ */
+ public Object nextElement() {
+ if (index < array.length) {
+ return array[index++];
+ }
+ throw new NoSuchElementException();
+ } // nextElement():Object
+
+ } // class ArrayEnumeration
+
+ //
+ // MAIN
+ //
+
+ /** Prints all of the constants to standard output. */
+ public static void main(String[] argv) {
+
+ print("SAX features:", SAX_FEATURE_PREFIX, fgSAXFeatures);
+ print("SAX properties:", SAX_PROPERTY_PREFIX, fgSAXProperties);
+ print("Xerces features:", XERCES_FEATURE_PREFIX, fgXercesFeatures);
+ print("Xerces properties:", XERCES_PROPERTY_PREFIX, fgXercesProperties);
+
+ } // main(String[])
+
+ /** Prints a list of features/properties. */
+ private static void print(String header, String prefix, Object[] array) {
+ System.out.print(header);
+ if (array.length > 0) {
+ System.out.println();
+ for (int i = 0; i < array.length; i++) {
+ System.out.print(" ");
+ System.out.print(prefix);
+ System.out.println(array[i]);
+ }
+ }
+ else {
+ System.out.println(" none.");
+ }
+ } // print(String,String,Object[])
+
+} // class Constants
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/ExternalSubsetResolver.java b/resources/xerces2-j-src/org/apache/xerces/impl/ExternalSubsetResolver.java
new file mode 100644
index 0000000..707dad7
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/ExternalSubsetResolver.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.io.IOException;
+
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.grammars.XMLDTDDescription;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+import org.apache.xerces.xni.parser.XMLInputSource;
+
+/**
+ * This interface extends XMLEntityResolver providing
+ * a method to resolve external subsets for documents which do not
+ * explicitly provide one. The application can register an object that
+ * implements this interface with the parser configuration. If registered,
+ * it will be queried to locate an external subset when none is provided,
+ * even for documents that do not contain DOCTYPE declarations. If the
+ * registered external subset resolver does not provide an external subset
+ * for a given document, it should return null .
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ *
+ * @version $Id$
+ */
+public interface ExternalSubsetResolver
+ extends XMLEntityResolver {
+
+ //
+ // ExternalSubsetResolver methods
+ //
+
+ /**
+ * Locates an external subset for documents which do not explicitly
+ * provide one. If no external subset is provided, this method should
+ * return null .
+ *
+ * @param grammarDescription a description of the DTD
+ *
+ * @throws XNIException Thrown on general error.
+ * @throws IOException Thrown if resolved entity stream cannot be
+ * opened or some other i/o error occurs.
+ */
+ public XMLInputSource getExternalSubset(XMLDTDDescription grammarDescription)
+ throws XNIException, IOException;
+
+} // interface ExternalSubsetResolver
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/RevalidationHandler.java b/resources/xerces2-j-src/org/apache/xerces/impl/RevalidationHandler.java
new file mode 100644
index 0000000..8e31a1b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/RevalidationHandler.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.parser.XMLDocumentFilter;
+/**
+ * DOM Revalidation handler adds additional functionality to XMLDocumentHandler
+ *
+ * @xerces.internal
+ * @author Elena Litani, IBM
+ * @version $Id$
+ */
+public interface RevalidationHandler extends XMLDocumentFilter {
+
+ /**
+ * Character content.
+ *
+ * @param data The character data.
+ * @param augs Augmentations
+ * @return True if data is whitespace only
+ */
+ public boolean characterData(String data, Augmentations augs);
+
+
+} // interface DOMRevalidationHandler
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/Version.java b/resources/xerces2-j-src/org/apache/xerces/impl/Version.java
new file mode 100644
index 0000000..b235961
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/Version.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+/**
+ * This class defines the version number of the parser.
+ *
+ * @version $Id$
+ */
+public class Version {
+
+ //
+ // Data
+ //
+
+ /** Version string.
+ * @deprecated getVersion() should be used instead. */
+ public static String fVersion = "@@VERSION@@";
+
+ private static final String fImmutableVersion = "@@VERSION@@";
+
+ // public methods
+
+ /* Print out the version information.
+ * @return the version of the parser.
+ */
+ public static String getVersion() {
+ return fImmutableVersion;
+ } // getVersion(): String
+
+ //
+ // MAIN
+ //
+
+ /**
+ * Prints out the version number to System.out. This is needed
+ * for the build system.
+ */
+ public static void main(String argv[]) {
+ System.out.println(fVersion);
+ }
+
+} // class Version
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XML11DTDScannerImpl.java b/resources/xerces2-j-src/org/apache/xerces/impl/XML11DTDScannerImpl.java
new file mode 100644
index 0000000..c8c39d2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XML11DTDScannerImpl.java
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.io.IOException;
+
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XML11Char;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.util.XMLStringBuffer;
+import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.XNIException;
+
+/**
+ * This class is responsible for scanning the declarations found
+ * in the internal and external subsets of a DTD in an XML document.
+ * The scanner acts as the sources for the DTD information which is
+ * communicated to the DTD handlers.
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/validation
+ * - http://apache.org/xml/features/scanner/notify-char-refs
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/entity-manager
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Arnaud Le Hors, IBM
+ * @author Andy Clark, IBM
+ * @author Glenn Marcy, IBM
+ * @author Eric Ye, IBM
+ *
+ * @version $Id$
+ */
+public class XML11DTDScannerImpl
+ extends XMLDTDScannerImpl {
+
+ /** String buffer. */
+ private final XMLStringBuffer fStringBuffer = new XMLStringBuffer();
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XML11DTDScannerImpl() {super();} // ()
+
+ /** Constructor for he use of non-XMLComponentManagers. */
+ public XML11DTDScannerImpl(SymbolTable symbolTable,
+ XMLErrorReporter errorReporter, XMLEntityManager entityManager) {
+ super(symbolTable, errorReporter, entityManager);
+ }
+
+ //
+ // XMLDTDScanner methods
+ //
+
+ //
+ // XMLScanner methods
+ //
+ // NOTE: this is a carbon copy of the code in XML11DocumentScannerImpl;
+ // we need to override these methods in both places. Ah for
+ // multiple inheritance...
+ // This needs to be refactored!!! - NG
+ /**
+ * Scans public ID literal.
+ *
+ * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
+ * [13] PubidChar::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
+ *
+ * The returned string is normalized according to the following rule,
+ * from http://www.w3.org/TR/REC-xml#dt-pubid:
+ *
+ * Before a match is attempted, all strings of white space in the public
+ * identifier must be normalized to single space characters (#x20), and
+ * leading and trailing white space must be removed.
+ *
+ * @param literal The string to fill in with the public ID literal.
+ * @return True on success.
+ *
+ * Note: This method uses fStringBuffer, anything in it at
+ * the time of calling is lost.
+ */
+ protected boolean scanPubidLiteral(XMLString literal)
+ throws IOException, XNIException
+ {
+ int quote = fEntityScanner.scanChar();
+ if (quote != '\'' && quote != '"') {
+ reportFatalError("QuoteRequiredInPublicID", null);
+ return false;
+ }
+
+ fStringBuffer.clear();
+ // skip leading whitespace
+ boolean skipSpace = true;
+ boolean dataok = true;
+ while (true) {
+ int c = fEntityScanner.scanChar();
+ // REVISIT: it could really only be \n or 0x20; all else is normalized, no? - neilg
+ if (c == ' ' || c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) {
+ if (!skipSpace) {
+ // take the first whitespace as a space and skip the others
+ fStringBuffer.append(' ');
+ skipSpace = true;
+ }
+ }
+ else if (c == quote) {
+ if (skipSpace) {
+ // if we finished on a space let's trim it
+ fStringBuffer.length--;
+ }
+ literal.setValues(fStringBuffer);
+ break;
+ }
+ else if (XMLChar.isPubid(c)) {
+ fStringBuffer.append((char)c);
+ skipSpace = false;
+ }
+ else if (c == -1) {
+ reportFatalError("PublicIDUnterminated", null);
+ return false;
+ }
+ else {
+ dataok = false;
+ reportFatalError("InvalidCharInPublicID",
+ new Object[]{Integer.toHexString(c)});
+ }
+ }
+ return dataok;
+ }
+
+ /**
+ * Normalize whitespace in an XMLString converting all whitespace
+ * characters to space characters.
+ */
+ protected void normalizeWhitespace(XMLString value) {
+ int end = value.offset + value.length;
+ for (int i = value.offset; i < end; ++i) {
+ int c = value.ch[i];
+ if (XMLChar.isSpace(c)) {
+ value.ch[i] = ' ';
+ }
+ }
+ }
+
+ /**
+ * Normalize whitespace in an XMLString converting all whitespace
+ * characters to space characters.
+ */
+ protected void normalizeWhitespace(XMLString value, int fromIndex) {
+ int end = value.offset + value.length;
+ for (int i = value.offset + fromIndex; i < end; ++i) {
+ int c = value.ch[i];
+ if (XMLChar.isSpace(c)) {
+ value.ch[i] = ' ';
+ }
+ }
+ }
+
+ /**
+ * Checks whether this string would be unchanged by normalization.
+ *
+ * @return -1 if the value would be unchanged by normalization,
+ * otherwise the index of the first whitespace character which
+ * would be transformed.
+ */
+ protected int isUnchangedByNormalization(XMLString value) {
+ int end = value.offset + value.length;
+ for (int i = value.offset; i < end; ++i) {
+ int c = value.ch[i];
+ if (XMLChar.isSpace(c)) {
+ return i - value.offset;
+ }
+ }
+ return -1;
+ }
+
+ // returns true if the given character is not
+ // valid with respect to the version of
+ // XML understood by this scanner.
+ protected boolean isInvalid(int value) {
+ return (!XML11Char.isXML11Valid(value));
+ } // isInvalid(int): boolean
+
+ // returns true if the given character is not
+ // valid or may not be used outside a character reference
+ // with respect to the version of XML understood by this scanner.
+ protected boolean isInvalidLiteral(int value) {
+ return (!XML11Char.isXML11ValidLiteral(value));
+ } // isInvalidLiteral(int): boolean
+
+ // returns true if the given character is
+ // a valid nameChar with respect to the version of
+ // XML understood by this scanner.
+ protected boolean isValidNameChar(int value) {
+ return (XML11Char.isXML11Name(value));
+ } // isValidNameChar(int): boolean
+
+ // returns true if the given character is
+ // a valid nameStartChar with respect to the version of
+ // XML understood by this scanner.
+ protected boolean isValidNameStartChar(int value) {
+ return (XML11Char.isXML11NameStart(value));
+ } // isValidNameStartChar(int): boolean
+
+ // returns true if the given character is
+ // a valid NCName character with respect to the version of
+ // XML understood by this scanner.
+ protected boolean isValidNCName(int value) {
+ return (XML11Char.isXML11NCName(value));
+ } // isValidNCName(int): boolean
+
+ // returns true if the given character is
+ // a valid high surrogate for a nameStartChar
+ // with respect to the version of XML understood
+ // by this scanner.
+ protected boolean isValidNameStartHighSurrogate(int value) {
+ return XML11Char.isXML11NameHighSurrogate(value);
+ } // isValidNameStartHighSurrogate(int): boolean
+
+ // note that, according to 4.3.4 of the XML 1.1 spec, XML 1.1
+ // documents may invoke 1.0 entities; thus either version decl (or none!)
+ // is allowed to appear in this context
+ protected boolean versionSupported(String version) {
+ return version.equals("1.1") || version.equals ("1.0");
+ } // versionSupported(String): boolean
+
+ // returns the error message key for unsupported
+ // versions of XML with respect to the version of
+ // XML understood by this scanner.
+ protected String getVersionNotSupportedKey () {
+ return "VersionNotSupported11";
+ } // getVersionNotSupportedKey: String
+
+} // class XML11DTDScannerImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XML11DocumentScannerImpl.java b/resources/xerces2-j-src/org/apache/xerces/impl/XML11DocumentScannerImpl.java
new file mode 100644
index 0000000..ce93297
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XML11DocumentScannerImpl.java
@@ -0,0 +1,548 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.io.IOException;
+
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.XML11Char;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.util.XMLStringBuffer;
+import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.XNIException;
+
+/**
+ * This class is responsible for scanning XML document structure
+ * and content. The scanner acts as the source for the document
+ * information which is communicated to the document handler.
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/namespaces
+ * - http://xml.org/sax/features/validation
+ * - http://apache.org/xml/features/nonvalidating/load-external-dtd
+ * - http://apache.org/xml/features/scanner/notify-char-refs
+ * - http://apache.org/xml/features/scanner/notify-builtin-refs
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/entity-manager
+ * - http://apache.org/xml/properties/internal/dtd-scanner
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Glenn Marcy, IBM
+ * @author Andy Clark, IBM
+ * @author Arnaud Le Hors, IBM
+ * @author Eric Ye, IBM
+ *
+ * @version $Id$
+ */
+public class XML11DocumentScannerImpl
+ extends XMLDocumentScannerImpl {
+
+ /** String. */
+ private final XMLString fString = new XMLString();
+
+ /** String buffer. */
+ private final XMLStringBuffer fStringBuffer = new XMLStringBuffer();
+ private final XMLStringBuffer fStringBuffer2 = new XMLStringBuffer();
+ private final XMLStringBuffer fStringBuffer3 = new XMLStringBuffer();
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XML11DocumentScannerImpl() {super();} // ()
+
+ //
+ // overridden methods
+ //
+
+ // XMLDocumentFragmentImpl methods
+
+ /**
+ * Scans element content.
+ *
+ * @return Returns the next character on the stream.
+ */
+ protected int scanContent() throws IOException, XNIException {
+
+ XMLString content = fString;
+ int c = fEntityScanner.scanContent(content);
+ if (c == '\r' || c == 0x85 || c == 0x2028) {
+ // happens when there is the character reference
+ // but scanContent doesn't do entity expansions...
+ // is this *really* necessary??? - NG
+ fEntityScanner.scanChar();
+ fStringBuffer.clear();
+ fStringBuffer.append(fString);
+ fStringBuffer.append((char)c);
+ content = fStringBuffer;
+ c = -1;
+ }
+ if (fDocumentHandler != null && content.length > 0) {
+ fDocumentHandler.characters(content, null);
+ }
+
+ if (c == ']' && fString.length == 0) {
+ fStringBuffer.clear();
+ fStringBuffer.append((char)fEntityScanner.scanChar());
+ // remember where we are in case we get an endEntity before we
+ // could flush the buffer out - this happens when we're parsing an
+ // entity which ends with a ]
+ fInScanContent = true;
+ //
+ // We work on a single character basis to handle cases such as:
+ // ']]]>' which we might otherwise miss.
+ //
+ if (fEntityScanner.skipChar(']')) {
+ fStringBuffer.append(']');
+ while (fEntityScanner.skipChar(']')) {
+ fStringBuffer.append(']');
+ }
+ if (fEntityScanner.skipChar('>')) {
+ reportFatalError("CDEndInContent", null);
+ }
+ }
+ if (fDocumentHandler != null && fStringBuffer.length != 0) {
+ fDocumentHandler.characters(fStringBuffer, null);
+ }
+ fInScanContent = false;
+ c = -1;
+ }
+ return c;
+
+ } // scanContent():int
+
+ /**
+ * Scans an attribute value and normalizes whitespace converting all
+ * whitespace characters to space characters.
+ *
+ * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"
+ *
+ * @param value The XMLString to fill in with the value.
+ * @param nonNormalizedValue The XMLString to fill in with the
+ * non-normalized value.
+ * @param atName The name of the attribute being parsed (for error msgs).
+ * @param checkEntities true if undeclared entities should be reported as VC violation,
+ * false if undeclared entities should be reported as WFC violation.
+ * @param eleName The name of element to which this attribute belongs.
+ *
+ * @return true if the non-normalized and normalized value are the same
+ *
+ * Note: This method uses fStringBuffer2, anything in it
+ * at the time of calling is lost.
+ **/
+ protected boolean scanAttributeValue(XMLString value,
+ XMLString nonNormalizedValue,
+ String atName,
+ boolean checkEntities,String eleName)
+ throws IOException, XNIException
+ {
+ // quote
+ int quote = fEntityScanner.peekChar();
+ if (quote != '\'' && quote != '"') {
+ reportFatalError("OpenQuoteExpected", new Object[]{eleName,atName});
+ }
+
+ fEntityScanner.scanChar();
+ int entityDepth = fEntityDepth;
+
+ int c = fEntityScanner.scanLiteral(quote, value);
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** scanLiteral -> \""
+ + value.toString() + "\"");
+ }
+
+ int fromIndex = 0;
+ if (c == quote && (fromIndex = isUnchangedByNormalization(value)) == -1) {
+ /** Both the non-normalized and normalized attribute values are equal. **/
+ nonNormalizedValue.setValues(value);
+ int cquote = fEntityScanner.scanChar();
+ if (cquote != quote) {
+ reportFatalError("CloseQuoteExpected", new Object[]{eleName,atName});
+ }
+ return true;
+ }
+ fStringBuffer2.clear();
+ fStringBuffer2.append(value);
+ normalizeWhitespace(value, fromIndex);
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** normalizeWhitespace -> \""
+ + value.toString() + "\"");
+ }
+ if (c != quote) {
+ fScanningAttribute = true;
+ fStringBuffer.clear();
+ do {
+ fStringBuffer.append(value);
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** value2: \""
+ + fStringBuffer.toString() + "\"");
+ }
+ if (c == '&') {
+ fEntityScanner.skipChar('&');
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append('&');
+ }
+ if (fEntityScanner.skipChar('#')) {
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append('#');
+ }
+ int ch = scanCharReferenceValue(fStringBuffer, fStringBuffer2);
+ if (ch != -1) {
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** value3: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ }
+ else {
+ String entityName = fEntityScanner.scanName();
+ if (entityName == null) {
+ reportFatalError("NameRequiredInReference", null);
+ }
+ else if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append(entityName);
+ }
+ if (!fEntityScanner.skipChar(';')) {
+ reportFatalError("SemicolonRequiredInReference",
+ new Object []{entityName});
+ }
+ else if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append(';');
+ }
+ if (entityName == fAmpSymbol) {
+ fStringBuffer.append('&');
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** value5: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ else if (entityName == fAposSymbol) {
+ fStringBuffer.append('\'');
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** value7: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ else if (entityName == fLtSymbol) {
+ fStringBuffer.append('<');
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** value9: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ else if (entityName == fGtSymbol) {
+ fStringBuffer.append('>');
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** valueB: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ else if (entityName == fQuotSymbol) {
+ fStringBuffer.append('"');
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** valueD: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ else {
+ if (fEntityManager.isExternalEntity(entityName)) {
+ reportFatalError("ReferenceToExternalEntity",
+ new Object[] { entityName });
+ }
+ else {
+ if (!fEntityManager.isDeclaredEntity(entityName)) {
+ //WFC & VC: Entity Declared
+ if (checkEntities) {
+ if (fValidation) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "EntityNotDeclared",
+ new Object[]{entityName},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ else {
+ reportFatalError("EntityNotDeclared",
+ new Object[]{entityName});
+ }
+ }
+ fEntityManager.startEntity(entityName, true);
+ }
+ }
+ }
+ }
+ else if (c == '<') {
+ reportFatalError("LessthanInAttValue",
+ new Object[] { eleName, atName });
+ fEntityScanner.scanChar();
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append((char)c);
+ }
+ }
+ else if (c == '%' || c == ']') {
+ fEntityScanner.scanChar();
+ fStringBuffer.append((char)c);
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append((char)c);
+ }
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** valueF: \""
+ + fStringBuffer.toString() + "\"");
+ }
+ }
+ // note that none of these characters should ever get through
+ // XML11EntityScanner. Not sure why
+ // this check was originally necessary. - NG
+ else if (c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) {
+ fEntityScanner.scanChar();
+ fStringBuffer.append(' ');
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append('\n');
+ }
+ }
+ else if (c != -1 && XMLChar.isHighSurrogate(c)) {
+ fStringBuffer3.clear();
+ if (scanSurrogates(fStringBuffer3)) {
+ fStringBuffer.append(fStringBuffer3);
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append(fStringBuffer3);
+ }
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** valueI: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ }
+ else if (c != -1 && isInvalidLiteral(c)) {
+ reportFatalError("InvalidCharInAttValue",
+ new Object[] {eleName, atName, Integer.toString(c, 16)});
+ fEntityScanner.scanChar();
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append((char)c);
+ }
+ }
+ c = fEntityScanner.scanLiteral(quote, value);
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append(value);
+ }
+ normalizeWhitespace(value);
+ } while (c != quote || entityDepth != fEntityDepth);
+ fStringBuffer.append(value);
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** valueN: \""
+ + fStringBuffer.toString() + "\"");
+ }
+ value.setValues(fStringBuffer);
+ fScanningAttribute = false;
+ }
+ nonNormalizedValue.setValues(fStringBuffer2);
+
+ // quote
+ int cquote = fEntityScanner.scanChar();
+ if (cquote != quote) {
+ reportFatalError("CloseQuoteExpected", new Object[]{eleName,atName});
+ }
+ return nonNormalizedValue.equals(value.ch, value.offset, value.length);
+ } // scanAttributeValue()
+
+ //
+ // XMLScanner methods
+ //
+ // NOTE: this is a carbon copy of the code in XML11DTDScannerImpl;
+ // we need to override these methods in both places.
+ // this needs to be refactored!!! - NG
+ /**
+ * Scans public ID literal.
+ *
+ * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
+ * [13] PubidChar::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
+ *
+ * The returned string is normalized according to the following rule,
+ * from http://www.w3.org/TR/REC-xml#dt-pubid:
+ *
+ * Before a match is attempted, all strings of white space in the public
+ * identifier must be normalized to single space characters (#x20), and
+ * leading and trailing white space must be removed.
+ *
+ * @param literal The string to fill in with the public ID literal.
+ * @return True on success.
+ *
+ * Note: This method uses fStringBuffer, anything in it at
+ * the time of calling is lost.
+ */
+ protected boolean scanPubidLiteral(XMLString literal)
+ throws IOException, XNIException
+ {
+ int quote = fEntityScanner.scanChar();
+ if (quote != '\'' && quote != '"') {
+ reportFatalError("QuoteRequiredInPublicID", null);
+ return false;
+ }
+
+ fStringBuffer.clear();
+ // skip leading whitespace
+ boolean skipSpace = true;
+ boolean dataok = true;
+ while (true) {
+ int c = fEntityScanner.scanChar();
+ // REVISIT: none of these except \n and 0x20 should make it past the entity scanner
+ if (c == ' ' || c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) {
+ if (!skipSpace) {
+ // take the first whitespace as a space and skip the others
+ fStringBuffer.append(' ');
+ skipSpace = true;
+ }
+ }
+ else if (c == quote) {
+ if (skipSpace) {
+ // if we finished on a space let's trim it
+ fStringBuffer.length--;
+ }
+ literal.setValues(fStringBuffer);
+ break;
+ }
+ else if (XMLChar.isPubid(c)) {
+ fStringBuffer.append((char)c);
+ skipSpace = false;
+ }
+ else if (c == -1) {
+ reportFatalError("PublicIDUnterminated", null);
+ return false;
+ }
+ else {
+ dataok = false;
+ reportFatalError("InvalidCharInPublicID",
+ new Object[]{Integer.toHexString(c)});
+ }
+ }
+ return dataok;
+ }
+
+ /**
+ * Normalize whitespace in an XMLString converting all whitespace
+ * characters to space characters.
+ */
+ protected void normalizeWhitespace(XMLString value) {
+ int end = value.offset + value.length;
+ for (int i = value.offset; i < end; ++i) {
+ int c = value.ch[i];
+ if (XMLChar.isSpace(c)) {
+ value.ch[i] = ' ';
+ }
+ }
+ }
+
+ /**
+ * Normalize whitespace in an XMLString converting all whitespace
+ * characters to space characters.
+ */
+ protected void normalizeWhitespace(XMLString value, int fromIndex) {
+ int end = value.offset + value.length;
+ for (int i = value.offset + fromIndex; i < end; ++i) {
+ int c = value.ch[i];
+ if (XMLChar.isSpace(c)) {
+ value.ch[i] = ' ';
+ }
+ }
+ }
+
+ /**
+ * Checks whether this string would be unchanged by normalization.
+ *
+ * @return -1 if the value would be unchanged by normalization,
+ * otherwise the index of the first whitespace character which
+ * would be transformed.
+ */
+ protected int isUnchangedByNormalization(XMLString value) {
+ int end = value.offset + value.length;
+ for (int i = value.offset; i < end; ++i) {
+ int c = value.ch[i];
+ if (XMLChar.isSpace(c)) {
+ return i - value.offset;
+ }
+ }
+ return -1;
+ }
+
+ // returns true if the given character is not
+ // valid with respect to the version of
+ // XML understood by this scanner.
+ protected boolean isInvalid(int value) {
+ return (XML11Char.isXML11Invalid(value));
+ } // isInvalid(int): boolean
+
+ // returns true if the given character is not
+ // valid or may not be used outside a character reference
+ // with respect to the version of XML understood by this scanner.
+ protected boolean isInvalidLiteral(int value) {
+ return (!XML11Char.isXML11ValidLiteral(value));
+ } // isInvalidLiteral(int): boolean
+
+ // returns true if the given character is
+ // a valid nameChar with respect to the version of
+ // XML understood by this scanner.
+ protected boolean isValidNameChar(int value) {
+ return (XML11Char.isXML11Name(value));
+ } // isValidNameChar(int): boolean
+
+ // returns true if the given character is
+ // a valid nameStartChar with respect to the version of
+ // XML understood by this scanner.
+ protected boolean isValidNameStartChar(int value) {
+ return (XML11Char.isXML11NameStart(value));
+ } // isValidNameStartChar(int): boolean
+
+ // returns true if the given character is
+ // a valid NCName character with respect to the version of
+ // XML understood by this scanner.
+ protected boolean isValidNCName(int value) {
+ return (XML11Char.isXML11NCName(value));
+ } // isValidNCName(int): boolean
+
+ // returns true if the given character is
+ // a valid high surrogate for a nameStartChar
+ // with respect to the version of XML understood
+ // by this scanner.
+ protected boolean isValidNameStartHighSurrogate(int value) {
+ return XML11Char.isXML11NameHighSurrogate(value);
+ } // isValidNameStartHighSurrogate(int): boolean
+
+ protected boolean versionSupported(String version) {
+ return (version.equals("1.1") || version.equals("1.0"));
+ } // versionSupported(String): boolean
+
+ // returns the error message key for unsupported
+ // versions of XML with respect to the version of
+ // XML understood by this scanner.
+ protected String getVersionNotSupportedKey () {
+ return "VersionNotSupported11";
+ } // getVersionNotSupportedKey: String
+
+} // class XML11DocumentScannerImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XML11EntityScanner.java b/resources/xerces2-j-src/org/apache/xerces/impl/XML11EntityScanner.java
new file mode 100644
index 0000000..0194205
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XML11EntityScanner.java
@@ -0,0 +1,1423 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.io.EOFException;
+import java.io.IOException;
+
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.XML11Char;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.util.XMLStringBuffer;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLString;
+
+/**
+ * Implements the entity scanner methods in
+ * the context of XML 1.1.
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ * @author Neil Graham, IBM
+ * @version $Id$
+ */
+public class XML11EntityScanner
+ extends XMLEntityScanner {
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XML11EntityScanner() {
+ super();
+ } // ()
+
+ //
+ // XMLEntityScanner methods
+ //
+
+ /**
+ * Returns the next character on the input.
+ *
+ * Note: The character is not consumed.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public int peekChar() throws IOException {
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // peek at character
+ int c = fCurrentEntity.ch[fCurrentEntity.position];
+
+ // return peeked character
+ if (fCurrentEntity.isExternal()) {
+ return (c != '\r' && c != 0x85 && c != 0x2028) ? c : '\n';
+ }
+ else {
+ return c;
+ }
+
+ } // peekChar():int
+
+ /**
+ * Returns the next character on the input.
+ *
+ * Note: The character is consumed.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public int scanChar() throws IOException {
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // scan character
+ int c = fCurrentEntity.ch[fCurrentEntity.position++];
+ boolean external = false;
+ if (c == '\n' ||
+ ((c == '\r' || c == 0x85 || c == 0x2028) && (external = fCurrentEntity.isExternal()))) {
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = (char)c;
+ load(1, false);
+ }
+ if (c == '\r' && external) {
+ int cc = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (cc != '\n' && cc != 0x85) {
+ fCurrentEntity.position--;
+ }
+ }
+ c = '\n';
+ }
+
+ // return character that was scanned
+ fCurrentEntity.columnNumber++;
+ return c;
+
+ } // scanChar():int
+
+ /**
+ * Returns a string matching the NMTOKEN production appearing immediately
+ * on the input as a symbol, or null if NMTOKEN Name string is present.
+ *
+ * Note: The NMTOKEN characters are consumed.
+ *
+ * Note: The string returned must be a symbol. The
+ * SymbolTable can be used for this purpose.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ *
+ * @see org.apache.xerces.util.SymbolTable
+ * @see org.apache.xerces.util.XML11Char#isXML11Name
+ */
+ public String scanNmtoken() throws IOException {
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // scan nmtoken
+ int offset = fCurrentEntity.position;
+
+ do {
+ char ch = fCurrentEntity.ch[fCurrentEntity.position];
+ if (XML11Char.isXML11Name(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ offset = 0;
+ if (load(length, false)) {
+ break;
+ }
+ }
+ }
+ else if (XML11Char.isXML11NameHighSurrogate(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ offset = 0;
+ if (load(length, false)) {
+ --fCurrentEntity.startPosition;
+ --fCurrentEntity.position;
+ break;
+ }
+ }
+ char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
+ if ( !XMLChar.isLowSurrogate(ch2) ||
+ !XML11Char.isXML11Name(XMLChar.supplemental(ch, ch2)) ) {
+ --fCurrentEntity.position;
+ break;
+ }
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ offset = 0;
+ if (load(length, false)) {
+ break;
+ }
+ }
+ }
+ else {
+ break;
+ }
+ }
+ while (true);
+
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length;
+
+ // return nmtoken
+ String symbol = null;
+ if (length > 0) {
+ symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
+ }
+ return symbol;
+
+ } // scanNmtoken():String
+
+ /**
+ * Returns a string matching the Name production appearing immediately
+ * on the input as a symbol, or null if no Name string is present.
+ *
+ * Note: The Name characters are consumed.
+ *
+ * Note: The string returned must be a symbol. The
+ * SymbolTable can be used for this purpose.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ *
+ * @see org.apache.xerces.util.SymbolTable
+ * @see org.apache.xerces.util.XML11Char#isXML11Name
+ * @see org.apache.xerces.util.XML11Char#isXML11NameStart
+ */
+ public String scanName() throws IOException {
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // scan name
+ int offset = fCurrentEntity.position;
+ char ch = fCurrentEntity.ch[offset];
+
+ if (XML11Char.isXML11NameStart(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = ch;
+ offset = 0;
+ if (load(1, false)) {
+ fCurrentEntity.columnNumber++;
+ String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
+ return symbol;
+ }
+ }
+ }
+ else if (XML11Char.isXML11NameHighSurrogate(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = ch;
+ offset = 0;
+ if (load(1, false)) {
+ --fCurrentEntity.position;
+ --fCurrentEntity.startPosition;
+ return null;
+ }
+ }
+ char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
+ if ( !XMLChar.isLowSurrogate(ch2) ||
+ !XML11Char.isXML11NameStart(XMLChar.supplemental(ch, ch2)) ) {
+ --fCurrentEntity.position;
+ return null;
+ }
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = ch;
+ fCurrentEntity.ch[1] = ch2;
+ offset = 0;
+ if (load(2, false)) {
+ fCurrentEntity.columnNumber += 2;
+ String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
+ return symbol;
+ }
+ }
+ }
+ else {
+ return null;
+ }
+
+ do {
+ ch = fCurrentEntity.ch[fCurrentEntity.position];
+ if (XML11Char.isXML11Name(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ offset = 0;
+ if (load(length, false)) {
+ break;
+ }
+ }
+ }
+ else if (XML11Char.isXML11NameHighSurrogate(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ offset = 0;
+ if (load(length, false)) {
+ --fCurrentEntity.position;
+ --fCurrentEntity.startPosition;
+ break;
+ }
+ }
+ char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
+ if ( !XMLChar.isLowSurrogate(ch2) ||
+ !XML11Char.isXML11Name(XMLChar.supplemental(ch, ch2)) ) {
+ --fCurrentEntity.position;
+ break;
+ }
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ offset = 0;
+ if (load(length, false)) {
+ break;
+ }
+ }
+ }
+ else {
+ break;
+ }
+ }
+ while (true);
+
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length;
+
+ // return name
+ String symbol = null;
+ if (length > 0) {
+ symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
+ }
+ return symbol;
+
+ } // scanName():String
+
+ /**
+ * Returns a string matching the NCName production appearing immediately
+ * on the input as a symbol, or null if no NCName string is present.
+ *
+ * Note: The NCName characters are consumed.
+ *
+ * Note: The string returned must be a symbol. The
+ * SymbolTable can be used for this purpose.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ *
+ * @see org.apache.xerces.util.SymbolTable
+ * @see org.apache.xerces.util.XML11Char#isXML11NCName
+ * @see org.apache.xerces.util.XML11Char#isXML11NCNameStart
+ */
+ public String scanNCName() throws IOException {
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // scan name
+ int offset = fCurrentEntity.position;
+ char ch = fCurrentEntity.ch[offset];
+
+ if (XML11Char.isXML11NCNameStart(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = ch;
+ offset = 0;
+ if (load(1, false)) {
+ fCurrentEntity.columnNumber++;
+ String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
+ return symbol;
+ }
+ }
+ }
+ else if (XML11Char.isXML11NameHighSurrogate(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = ch;
+ offset = 0;
+ if (load(1, false)) {
+ --fCurrentEntity.position;
+ --fCurrentEntity.startPosition;
+ return null;
+ }
+ }
+ char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
+ if ( !XMLChar.isLowSurrogate(ch2) ||
+ !XML11Char.isXML11NCNameStart(XMLChar.supplemental(ch, ch2)) ) {
+ --fCurrentEntity.position;
+ return null;
+ }
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = ch;
+ fCurrentEntity.ch[1] = ch2;
+ offset = 0;
+ if (load(2, false)) {
+ fCurrentEntity.columnNumber += 2;
+ String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
+ return symbol;
+ }
+ }
+ }
+ else {
+ return null;
+ }
+
+ do {
+ ch = fCurrentEntity.ch[fCurrentEntity.position];
+ if (XML11Char.isXML11NCName(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ offset = 0;
+ if (load(length, false)) {
+ break;
+ }
+ }
+ }
+ else if (XML11Char.isXML11NameHighSurrogate(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ offset = 0;
+ if (load(length, false)) {
+ --fCurrentEntity.startPosition;
+ --fCurrentEntity.position;
+ break;
+ }
+ }
+ char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
+ if ( !XMLChar.isLowSurrogate(ch2) ||
+ !XML11Char.isXML11NCName(XMLChar.supplemental(ch, ch2)) ) {
+ --fCurrentEntity.position;
+ break;
+ }
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ offset = 0;
+ if (load(length, false)) {
+ break;
+ }
+ }
+ }
+ else {
+ break;
+ }
+ }
+ while (true);
+
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length;
+
+ // return name
+ String symbol = null;
+ if (length > 0) {
+ symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
+ }
+ return symbol;
+
+ } // scanNCName():String
+
+ /**
+ * Scans a qualified name from the input, setting the fields of the
+ * QName structure appropriately.
+ *
+ * Note: The qualified name characters are consumed.
+ *
+ * Note: The strings used to set the values of the
+ * QName structure must be symbols. The SymbolTable can be used for
+ * this purpose.
+ *
+ * @param qname The qualified name structure to fill.
+ *
+ * @return Returns true if a qualified name appeared immediately on
+ * the input and was scanned, false otherwise.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ *
+ * @see org.apache.xerces.util.SymbolTable
+ * @see org.apache.xerces.util.XML11Char#isXML11Name
+ * @see org.apache.xerces.util.XML11Char#isXML11NameStart
+ */
+ public boolean scanQName(QName qname) throws IOException {
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // scan qualified name
+ int offset = fCurrentEntity.position;
+ char ch = fCurrentEntity.ch[offset];
+
+ if (XML11Char.isXML11NCNameStart(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = ch;
+ offset = 0;
+ if (load(1, false)) {
+ fCurrentEntity.columnNumber++;
+ String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
+ qname.setValues(null, name, name, null);
+ return true;
+ }
+ }
+ }
+ else if (XML11Char.isXML11NameHighSurrogate(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = ch;
+ offset = 0;
+ if (load(1, false)) {
+ --fCurrentEntity.startPosition;
+ --fCurrentEntity.position;
+ return false;
+ }
+ }
+ char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
+ if ( !XMLChar.isLowSurrogate(ch2) ||
+ !XML11Char.isXML11NCNameStart(XMLChar.supplemental(ch, ch2)) ) {
+ --fCurrentEntity.position;
+ return false;
+ }
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = ch;
+ fCurrentEntity.ch[1] = ch2;
+ offset = 0;
+ if (load(2, false)) {
+ fCurrentEntity.columnNumber += 2;
+ String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
+ qname.setValues(null, name, name, null);
+ return true;
+ }
+ }
+ }
+ else {
+ return false;
+ }
+
+ int index = -1;
+ boolean sawIncompleteSurrogatePair = false;
+ do {
+ ch = fCurrentEntity.ch[fCurrentEntity.position];
+ if (XML11Char.isXML11Name(ch)) {
+ if (ch == ':') {
+ if (index != -1) {
+ break;
+ }
+ index = fCurrentEntity.position;
+ }
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ if (index != -1) {
+ index = index - offset;
+ }
+ offset = 0;
+ if (load(length, false)) {
+ break;
+ }
+ }
+ }
+ else if (XML11Char.isXML11NameHighSurrogate(ch)) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ if (index != -1) {
+ index = index - offset;
+ }
+ offset = 0;
+ if (load(length, false)) {
+ sawIncompleteSurrogatePair = true;
+ --fCurrentEntity.startPosition;
+ --fCurrentEntity.position;
+ break;
+ }
+ }
+ char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
+ if ( !XMLChar.isLowSurrogate(ch2) ||
+ !XML11Char.isXML11Name(XMLChar.supplemental(ch, ch2)) ) {
+ sawIncompleteSurrogatePair = true;
+ --fCurrentEntity.position;
+ break;
+ }
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ if (index != -1) {
+ index = index - offset;
+ }
+ offset = 0;
+ if (load(length, false)) {
+ break;
+ }
+ }
+ }
+ else {
+ break;
+ }
+ }
+ while (true);
+
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length;
+
+ if (length > 0) {
+ String prefix = null;
+ String localpart = null;
+ String rawname = fSymbolTable.addSymbol(fCurrentEntity.ch,
+ offset, length);
+ if (index != -1) {
+ int prefixLength = index - offset;
+ prefix = fSymbolTable.addSymbol(fCurrentEntity.ch,
+ offset, prefixLength);
+ int len = length - prefixLength - 1;
+ int startLocal = index +1;
+ if (!XML11Char.isXML11NCNameStart(fCurrentEntity.ch[startLocal]) &&
+ (!XML11Char.isXML11NameHighSurrogate(fCurrentEntity.ch[startLocal]) ||
+ sawIncompleteSurrogatePair)){
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "IllegalQName",
+ null,
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ localpart = fSymbolTable.addSymbol(fCurrentEntity.ch,
+ index + 1, len);
+
+ }
+ else {
+ localpart = rawname;
+ }
+ qname.setValues(prefix, localpart, rawname, null);
+ return true;
+ }
+ return false;
+
+ } // scanQName(QName):boolean
+
+ /**
+ * Scans a range of parsed character data, setting the fields of the
+ * XMLString structure, appropriately.
+ *
+ * Note: The characters are consumed.
+ *
+ * Note: This method does not guarantee to return
+ * the longest run of parsed character data. This method may return
+ * before markup due to reaching the end of the input buffer or any
+ * other reason.
+ *
+ * Note: The fields contained in the XMLString
+ * structure are not guaranteed to remain valid upon subsequent calls
+ * to the entity scanner. Therefore, the caller is responsible for
+ * immediately using the returned character data or making a copy of
+ * the character data.
+ *
+ * @param content The content structure to fill.
+ *
+ * @return Returns the next character on the input, if known. This
+ * value may be -1 but this does note designate
+ * end of file.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public int scanContent(XMLString content) throws IOException {
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+ else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
+ load(1, false);
+ fCurrentEntity.position = 0;
+ fCurrentEntity.startPosition = 0;
+ }
+
+ // normalize newlines
+ int offset = fCurrentEntity.position;
+ int c = fCurrentEntity.ch[offset];
+ int newlines = 0;
+ boolean external = fCurrentEntity.isExternal();
+ if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
+ do {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if ((c == '\r' ) && external) {
+ newlines++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ offset = 0;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = newlines;
+ fCurrentEntity.startPosition = newlines;
+ if (load(newlines, false)) {
+ break;
+ }
+ }
+ int cc = fCurrentEntity.ch[fCurrentEntity.position];
+ if (cc == '\n' || cc == 0x85) {
+ fCurrentEntity.position++;
+ offset++;
+ }
+ /*** NEWLINE NORMALIZATION ***/
+ else {
+ newlines++;
+ }
+ }
+ else if (c == '\n' || ((c == 0x85 || c == 0x2028) && external)) {
+ newlines++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ offset = 0;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = newlines;
+ fCurrentEntity.startPosition = newlines;
+ if (load(newlines, false)) {
+ break;
+ }
+ }
+ }
+ else {
+ fCurrentEntity.position--;
+ break;
+ }
+ } while (fCurrentEntity.position < fCurrentEntity.count - 1);
+ for (int i = offset; i < fCurrentEntity.position; i++) {
+ fCurrentEntity.ch[i] = '\n';
+ }
+ int length = fCurrentEntity.position - offset;
+ if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ content.setValues(fCurrentEntity.ch, offset, length);
+ return -1;
+ }
+ }
+
+ // inner loop, scanning for content
+ if (external) {
+ while (fCurrentEntity.position < fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (!XML11Char.isXML11Content(c) || c == 0x85 || c == 0x2028) {
+ fCurrentEntity.position--;
+ break;
+ }
+ }
+ }
+ else {
+ while (fCurrentEntity.position < fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ // In internal entities control characters are allowed to appear unescaped.
+ if (!XML11Char.isXML11InternalEntityContent(c)) {
+ fCurrentEntity.position--;
+ break;
+ }
+ }
+ }
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length - newlines;
+ content.setValues(fCurrentEntity.ch, offset, length);
+
+ // return next character
+ if (fCurrentEntity.position != fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position];
+ // REVISIT: Does this need to be updated to fix the
+ // #x0D ^#x0A newline normalization problem? -Ac
+ if ((c == '\r' || c == 0x85 || c == 0x2028) && external) {
+ c = '\n';
+ }
+ }
+ else {
+ c = -1;
+ }
+ return c;
+
+ } // scanContent(XMLString):int
+
+ /**
+ * Scans a range of attribute value data, setting the fields of the
+ * XMLString structure, appropriately.
+ *
+ * Note: The characters are consumed.
+ *
+ * Note: This method does not guarantee to return
+ * the longest run of attribute value data. This method may return
+ * before the quote character due to reaching the end of the input
+ * buffer or any other reason.
+ *
+ * Note: The fields contained in the XMLString
+ * structure are not guaranteed to remain valid upon subsequent calls
+ * to the entity scanner. Therefore, the caller is responsible for
+ * immediately using the returned character data or making a copy of
+ * the character data.
+ *
+ * @param quote The quote character that signifies the end of the
+ * attribute value data.
+ * @param content The content structure to fill.
+ *
+ * @return Returns the next character on the input, if known. This
+ * value may be -1 but this does note designate
+ * end of file.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public int scanLiteral(int quote, XMLString content)
+ throws IOException {
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+ else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
+ load(1, false);
+ fCurrentEntity.startPosition = 0;
+ fCurrentEntity.position = 0;
+ }
+
+ // normalize newlines
+ int offset = fCurrentEntity.position;
+ int c = fCurrentEntity.ch[offset];
+ int newlines = 0;
+ boolean external = fCurrentEntity.isExternal();
+ if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
+ do {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if ((c == '\r' ) && external) {
+ newlines++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ offset = 0;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = newlines;
+ fCurrentEntity.startPosition = newlines;
+ if (load(newlines, false)) {
+ break;
+ }
+ }
+ int cc = fCurrentEntity.ch[fCurrentEntity.position];
+ if (cc == '\n' || cc == 0x85) {
+ fCurrentEntity.position++;
+ offset++;
+ }
+ /*** NEWLINE NORMALIZATION ***/
+ else {
+ newlines++;
+ }
+ }
+ else if (c == '\n' || ((c == 0x85 || c == 0x2028) && external)) {
+ newlines++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ offset = 0;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = newlines;
+ fCurrentEntity.startPosition = newlines;
+ if (load(newlines, false)) {
+ break;
+ }
+ }
+ }
+ else {
+ fCurrentEntity.position--;
+ break;
+ }
+ } while (fCurrentEntity.position < fCurrentEntity.count - 1);
+ for (int i = offset; i < fCurrentEntity.position; i++) {
+ fCurrentEntity.ch[i] = '\n';
+ }
+ int length = fCurrentEntity.position - offset;
+ if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ content.setValues(fCurrentEntity.ch, offset, length);
+ return -1;
+ }
+ }
+
+ // scan literal value
+ if (external) {
+ while (fCurrentEntity.position < fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (c == quote || c == '%' || !XML11Char.isXML11Content(c)
+ || c == 0x85 || c == 0x2028) {
+ fCurrentEntity.position--;
+ break;
+ }
+ }
+ }
+ else {
+ while (fCurrentEntity.position < fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ // In internal entities control characters are allowed to appear unescaped.
+ if ((c == quote && !fCurrentEntity.literal)
+ || c == '%' || !XML11Char.isXML11InternalEntityContent(c)) {
+ fCurrentEntity.position--;
+ break;
+ }
+ }
+ }
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length - newlines;
+ content.setValues(fCurrentEntity.ch, offset, length);
+
+ // return next character
+ if (fCurrentEntity.position != fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position];
+ // NOTE: We don't want to accidentally signal the
+ // end of the literal if we're expanding an
+ // entity appearing in the literal. -Ac
+ if (c == quote && fCurrentEntity.literal) {
+ c = -1;
+ }
+ }
+ else {
+ c = -1;
+ }
+ return c;
+
+ } // scanLiteral(int,XMLString):int
+
+ /**
+ * Scans a range of character data up to the specicied delimiter,
+ * setting the fields of the XMLString structure, appropriately.
+ *
+ * Note: The characters are consumed.
+ *
+ * Note: This assumes that the internal buffer is
+ * at least the same size, or bigger, than the length of the delimiter
+ * and that the delimiter contains at least one character.
+ *
+ * Note: This method does not guarantee to return
+ * the longest run of character data. This method may return before
+ * the delimiter due to reaching the end of the input buffer or any
+ * other reason.
+ *
+ * Note: The fields contained in the XMLString
+ * structure are not guaranteed to remain valid upon subsequent calls
+ * to the entity scanner. Therefore, the caller is responsible for
+ * immediately using the returned character data or making a copy of
+ * the character data.
+ *
+ * @param delimiter The string that signifies the end of the character
+ * data to be scanned.
+ * @param buffer The XMLStringBuffer to fill.
+ *
+ * @return Returns true if there is more data to scan, false otherwise.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public boolean scanData(String delimiter, XMLStringBuffer buffer)
+ throws IOException {
+
+ boolean done = false;
+ int delimLen = delimiter.length();
+ char charAt0 = delimiter.charAt(0);
+ boolean external = fCurrentEntity.isExternal();
+ do {
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ boolean bNextEntity = false;
+
+ while ((fCurrentEntity.position >= fCurrentEntity.count - delimLen)
+ && (!bNextEntity))
+ {
+ System.arraycopy(fCurrentEntity.ch,
+ fCurrentEntity.position,
+ fCurrentEntity.ch,
+ 0,
+ fCurrentEntity.count - fCurrentEntity.position);
+
+ bNextEntity = load(fCurrentEntity.count - fCurrentEntity.position, false);
+ fCurrentEntity.position = 0;
+ fCurrentEntity.startPosition = 0;
+ }
+
+ if (fCurrentEntity.position >= fCurrentEntity.count - delimLen) {
+ // something must be wrong with the input: e.g., file ends an unterminated comment
+ int length = fCurrentEntity.count - fCurrentEntity.position;
+ buffer.append (fCurrentEntity.ch, fCurrentEntity.position, length);
+ fCurrentEntity.columnNumber += fCurrentEntity.count;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = fCurrentEntity.count;
+ fCurrentEntity.startPosition = fCurrentEntity.count;
+ load(0,true);
+ return false;
+ }
+
+ // normalize newlines
+ int offset = fCurrentEntity.position;
+ int c = fCurrentEntity.ch[offset];
+ int newlines = 0;
+ if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
+ do {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if ((c == '\r' ) && external) {
+ newlines++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ offset = 0;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = newlines;
+ fCurrentEntity.startPosition = newlines;
+ if (load(newlines, false)) {
+ break;
+ }
+ }
+ int cc = fCurrentEntity.ch[fCurrentEntity.position];
+ if (cc == '\n' || cc == 0x85) {
+ fCurrentEntity.position++;
+ offset++;
+ }
+ /*** NEWLINE NORMALIZATION ***/
+ else {
+ newlines++;
+ }
+ }
+ else if (c == '\n' || ((c == 0x85 || c == 0x2028) && external)) {
+ newlines++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ offset = 0;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = newlines;
+ fCurrentEntity.startPosition = newlines;
+ fCurrentEntity.count = newlines;
+ if (load(newlines, false)) {
+ break;
+ }
+ }
+ }
+ else {
+ fCurrentEntity.position--;
+ break;
+ }
+ } while (fCurrentEntity.position < fCurrentEntity.count - 1);
+ for (int i = offset; i < fCurrentEntity.position; i++) {
+ fCurrentEntity.ch[i] = '\n';
+ }
+ int length = fCurrentEntity.position - offset;
+ if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ buffer.append(fCurrentEntity.ch, offset, length);
+ return true;
+ }
+ }
+
+ // iterate over buffer looking for delimiter
+ if (external) {
+ OUTER: while (fCurrentEntity.position < fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (c == charAt0) {
+ // looks like we just hit the delimiter
+ int delimOffset = fCurrentEntity.position - 1;
+ for (int i = 1; i < delimLen; i++) {
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.position -= i;
+ break OUTER;
+ }
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (delimiter.charAt(i) != c) {
+ fCurrentEntity.position--;
+ break;
+ }
+ }
+ if (fCurrentEntity.position == delimOffset + delimLen) {
+ done = true;
+ break;
+ }
+ }
+ else if (c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) {
+ fCurrentEntity.position--;
+ break;
+ }
+ // In external entities control characters cannot appear
+ // as literals so do not skip over them.
+ else if (!XML11Char.isXML11ValidLiteral(c)) {
+ fCurrentEntity.position--;
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length - newlines;
+ buffer.append(fCurrentEntity.ch, offset, length);
+ return true;
+ }
+ }
+ }
+ else {
+ OUTER: while (fCurrentEntity.position < fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (c == charAt0) {
+ // looks like we just hit the delimiter
+ int delimOffset = fCurrentEntity.position - 1;
+ for (int i = 1; i < delimLen; i++) {
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.position -= i;
+ break OUTER;
+ }
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (delimiter.charAt(i) != c) {
+ fCurrentEntity.position--;
+ break;
+ }
+ }
+ if (fCurrentEntity.position == delimOffset + delimLen) {
+ done = true;
+ break;
+ }
+ }
+ else if (c == '\n') {
+ fCurrentEntity.position--;
+ break;
+ }
+ // Control characters are allowed to appear as literals
+ // in internal entities.
+ else if (!XML11Char.isXML11Valid(c)) {
+ fCurrentEntity.position--;
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length - newlines;
+ buffer.append(fCurrentEntity.ch, offset, length);
+ return true;
+ }
+ }
+ }
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length - newlines;
+ if (done) {
+ length -= delimLen;
+ }
+ buffer.append(fCurrentEntity.ch, offset, length);
+
+ // return true if string was skipped
+ } while (!done);
+ return !done;
+
+ } // scanData(String,XMLString)
+
+ /**
+ * Skips a character appearing immediately on the input.
+ *
+ * Note: The character is consumed only if it matches
+ * the specified character.
+ *
+ * @param c The character to skip.
+ *
+ * @return Returns true if the character was skipped.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public boolean skipChar(int c) throws IOException {
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // skip character
+ int cc = fCurrentEntity.ch[fCurrentEntity.position];
+ if (cc == c) {
+ fCurrentEntity.position++;
+ if (c == '\n') {
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ }
+ else {
+ fCurrentEntity.columnNumber++;
+ }
+ return true;
+ }
+ else if (c == '\n' && ((cc == 0x2028 || cc == 0x85) && fCurrentEntity.isExternal())) {
+ fCurrentEntity.position++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ return true;
+ }
+ else if (c == '\n' && (cc == '\r' ) && fCurrentEntity.isExternal()) {
+ // handle newlines
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = (char)cc;
+ load(1, false);
+ }
+ int ccc = fCurrentEntity.ch[++fCurrentEntity.position];
+ if (ccc == '\n' || ccc == 0x85) {
+ fCurrentEntity.position++;
+ }
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ return true;
+ }
+
+ // character was not skipped
+ return false;
+
+ } // skipChar(int):boolean
+
+ /**
+ * Skips space characters appearing immediately on the input.
+ *
+ * Note: The characters are consumed only if they are
+ * space characters.
+ *
+ * @return Returns true if at least one space character was skipped.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ *
+ * @see org.apache.xerces.util.XMLChar#isSpace
+ * @see org.apache.xerces.util.XML11Char#isXML11Space
+ */
+ public boolean skipSpaces() throws IOException {
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // skip spaces
+ int c = fCurrentEntity.ch[fCurrentEntity.position];
+
+ // External -- Match: S + 0x85 + 0x2028, and perform end of line normalization
+ if (fCurrentEntity.isExternal()) {
+ if (XML11Char.isXML11Space(c)) {
+ do {
+ boolean entityChanged = false;
+ // handle newlines
+ if (c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) {
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ fCurrentEntity.ch[0] = (char)c;
+ entityChanged = load(1, true);
+ if (!entityChanged) {
+ // the load change the position to be 1,
+ // need to restore it when entity not changed
+ fCurrentEntity.startPosition = 0;
+ fCurrentEntity.position = 0;
+ }
+ }
+ if (c == '\r') {
+ // REVISIT: Does this need to be updated to fix the
+ // #x0D ^#x0A newline normalization problem? -Ac
+ int cc = fCurrentEntity.ch[++fCurrentEntity.position];
+ if (cc != '\n' && cc != 0x85 ) {
+ fCurrentEntity.position--;
+ }
+ }
+ }
+ else {
+ fCurrentEntity.columnNumber++;
+ }
+ // load more characters, if needed
+ if (!entityChanged)
+ fCurrentEntity.position++;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+ } while (XML11Char.isXML11Space(c = fCurrentEntity.ch[fCurrentEntity.position]));
+ return true;
+ }
+ }
+ // Internal -- Match: S (only)
+ else if (XMLChar.isSpace(c)) {
+ do {
+ boolean entityChanged = false;
+ // handle newlines
+ if (c == '\n') {
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ fCurrentEntity.ch[0] = (char)c;
+ entityChanged = load(1, true);
+ if (!entityChanged) {
+ // the load change the position to be 1,
+ // need to restore it when entity not changed
+ fCurrentEntity.startPosition = 0;
+ fCurrentEntity.position = 0;
+ }
+ }
+ }
+ else {
+ fCurrentEntity.columnNumber++;
+ }
+ // load more characters, if needed
+ if (!entityChanged)
+ fCurrentEntity.position++;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+ } while (XMLChar.isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
+ return true;
+ }
+
+ // no spaces were found
+ return false;
+
+ } // skipSpaces():boolean
+
+ /**
+ * Skips the specified string appearing immediately on the input.
+ *
+ * Note: The characters are consumed only if they are
+ * space characters.
+ *
+ * @param s The string to skip.
+ *
+ * @return Returns true if the string was skipped.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public boolean skipString(String s) throws IOException {
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // skip string
+ final int length = s.length();
+ for (int i = 0; i < length; i++) {
+ char c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (c != s.charAt(i)) {
+ fCurrentEntity.position -= i + 1;
+ return false;
+ }
+ if (i < length - 1 && fCurrentEntity.position == fCurrentEntity.count) {
+ System.arraycopy(fCurrentEntity.ch, fCurrentEntity.count - i - 1, fCurrentEntity.ch, 0, i + 1);
+ // REVISIT: Can a string to be skipped cross an
+ // entity boundary? -Ac
+ if (load(i + 1, false)) {
+ fCurrentEntity.startPosition -= i + 1;
+ fCurrentEntity.position -= i + 1;
+ return false;
+ }
+ }
+ }
+ fCurrentEntity.columnNumber += length;
+ return true;
+
+ } // skipString(String):boolean
+
+} // class XML11EntityScanner
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XML11NSDocumentScannerImpl.java b/resources/xerces2-j-src/org/apache/xerces/impl/XML11NSDocumentScannerImpl.java
new file mode 100644
index 0000000..4c3aaec
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XML11NSDocumentScannerImpl.java
@@ -0,0 +1,842 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.io.IOException;
+
+import org.apache.xerces.impl.dtd.XMLDTDValidatorFilter;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.XMLAttributesImpl;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLDocumentHandler;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLDocumentSource;
+
+/**
+ * The scanner acts as the source for the document
+ * information which is communicated to the document handler.
+ *
+ * This class scans an XML document, checks if document has a DTD, and if
+ * DTD is not found the scanner will remove the DTD Validator from the pipeline and perform
+ * namespace binding.
+ *
+ * Note: This scanner should only be used when the namespace processing is on!
+ *
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/namespaces {true} -- if the value of this
+ * feature is set to false this scanner must not be used.
+ * - http://xml.org/sax/features/validation
+ * - http://apache.org/xml/features/nonvalidating/load-external-dtd
+ * - http://apache.org/xml/features/scanner/notify-char-refs
+ * - http://apache.org/xml/features/scanner/notify-builtin-refs
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/entity-manager
+ * - http://apache.org/xml/properties/internal/dtd-scanner
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani, IBM
+ * @author Michael Glavassevich, IBM
+ *
+ * @version $Id$
+ */
+public class XML11NSDocumentScannerImpl extends XML11DocumentScannerImpl {
+
+ /**
+ * If is true, the dtd validator is no longer in the pipeline
+ * and the scanner should bind namespaces
+ */
+ protected boolean fBindNamespaces;
+
+ /**
+ * If validating parser, make sure we report an error in the
+ * scanner if DTD grammar is missing.
+ */
+ protected boolean fPerformValidation;
+
+ // private data
+ //
+
+ /** DTD validator */
+ private XMLDTDValidatorFilter fDTDValidator;
+
+ /**
+ * Saw spaces after element name or between attributes.
+ *
+ * This is reserved for the case where scanning of a start element spans
+ * several methods, as is the case when scanning the start of a root element
+ * where a DTD external subset may be read after scanning the element name.
+ */
+ private boolean fSawSpace;
+
+ /**
+ * The scanner is responsible for removing DTD validator
+ * from the pipeline if it is not needed.
+ *
+ * @param validator the DTD validator from the pipeline
+ */
+ public void setDTDValidator(XMLDTDValidatorFilter validator) {
+ fDTDValidator = validator;
+ }
+
+ /**
+ * Scans a start element. This method will handle the binding of
+ * namespace information and notifying the handler of the start
+ * of the element.
+ *
+ *
+ * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
+ * [40] STag ::= '<' Name (S Attribute)* S? '>'
+ *
+ *
+ * Note: This method assumes that the leading
+ * '<' character has been consumed.
+ *
+ * Note: This method uses the fElementQName and
+ * fAttributes variables. The contents of these variables will be
+ * destroyed. The caller should copy important information out of
+ * these variables before calling this method.
+ *
+ * @return True if element is empty. (i.e. It matches
+ * production [44].
+ */
+ protected boolean scanStartElement() throws IOException, XNIException {
+ if (DEBUG_CONTENT_SCANNING)
+ System.out.println(">>> scanStartElementNS()");
+
+ // Note: namespace processing is on by default
+ fEntityScanner.scanQName(fElementQName);
+ // REVISIT - [Q] Why do we need this local variable? -- mrglavas
+ String rawname = fElementQName.rawname;
+ if (fBindNamespaces) {
+ fNamespaceContext.pushContext();
+ if (fScannerState == SCANNER_STATE_ROOT_ELEMENT) {
+ if (fPerformValidation) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XML_DOMAIN,
+ "MSG_GRAMMAR_NOT_FOUND",
+ new Object[] { rawname },
+ XMLErrorReporter.SEVERITY_ERROR);
+
+ if (fDoctypeName == null
+ || !fDoctypeName.equals(rawname)) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XML_DOMAIN,
+ "RootElementTypeMustMatchDoctypedecl",
+ new Object[] { fDoctypeName, rawname },
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ }
+ }
+
+ // push element stack
+ fCurrentElement = fElementStack.pushElement(fElementQName);
+
+ // attributes
+ boolean empty = false;
+ fAttributes.removeAllAttributes();
+ do {
+ // spaces
+ boolean sawSpace = fEntityScanner.skipSpaces();
+
+ // end tag?
+ int c = fEntityScanner.peekChar();
+ if (c == '>') {
+ fEntityScanner.scanChar();
+ break;
+ } else if (c == '/') {
+ fEntityScanner.scanChar();
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError(
+ "ElementUnterminated",
+ new Object[] { rawname });
+ }
+ empty = true;
+ break;
+ } else if (!isValidNameStartChar(c) || !sawSpace) {
+ // Second chance. Check if this character is a high
+ // surrogate of a valid name start character.
+ if (!isValidNameStartHighSurrogate(c) || !sawSpace) {
+ reportFatalError(
+ "ElementUnterminated",
+ new Object[] { rawname });
+ }
+ }
+
+ // attributes
+ scanAttribute(fAttributes);
+
+ } while (true);
+
+ if (fBindNamespaces) {
+ // REVISIT: is it required? forbit xmlns prefix for element
+ if (fElementQName.prefix == XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementXMLNSPrefix",
+ new Object[] { fElementQName.rawname },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // bind the element
+ String prefix =
+ fElementQName.prefix != null
+ ? fElementQName.prefix
+ : XMLSymbols.EMPTY_STRING;
+ // assign uri to the element
+ fElementQName.uri = fNamespaceContext.getURI(prefix);
+ // make sure that object in the element stack is updated as well
+ fCurrentElement.uri = fElementQName.uri;
+
+ if (fElementQName.prefix == null && fElementQName.uri != null) {
+ fElementQName.prefix = XMLSymbols.EMPTY_STRING;
+ // making sure that the object in the element stack is updated too.
+ fCurrentElement.prefix = XMLSymbols.EMPTY_STRING;
+ }
+ if (fElementQName.prefix != null && fElementQName.uri == null) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementPrefixUnbound",
+ new Object[] {
+ fElementQName.prefix,
+ fElementQName.rawname },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // bind attributes (xmlns are already bound bellow)
+ int length = fAttributes.getLength();
+ for (int i = 0; i < length; i++) {
+ fAttributes.getName(i, fAttributeQName);
+
+ String aprefix =
+ fAttributeQName.prefix != null
+ ? fAttributeQName.prefix
+ : XMLSymbols.EMPTY_STRING;
+ String uri = fNamespaceContext.getURI(aprefix);
+ // REVISIT: try removing the first "if" and see if it is faster.
+ //
+ if (fAttributeQName.uri != null
+ && fAttributeQName.uri == uri) {
+ continue;
+ }
+ if (aprefix != XMLSymbols.EMPTY_STRING) {
+ fAttributeQName.uri = uri;
+ if (uri == null) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributePrefixUnbound",
+ new Object[] {
+ fElementQName.rawname,
+ fAttributeQName.rawname,
+ aprefix },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ fAttributes.setURI(i, uri);
+ }
+ }
+
+ if (length > 1) {
+ QName name = fAttributes.checkDuplicatesNS();
+ if (name != null) {
+ if (name.uri != null) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNSNotUnique",
+ new Object[] {
+ fElementQName.rawname,
+ name.localpart,
+ name.uri },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ } else {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNotUnique",
+ new Object[] {
+ fElementQName.rawname,
+ name.rawname },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ }
+ }
+
+ // call handler
+ if (fDocumentHandler != null) {
+ if (empty) {
+
+ //decrease the markup depth..
+ fMarkupDepth--;
+
+ // check that this element was opened in the same entity
+ if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
+ reportFatalError(
+ "ElementEntityMismatch",
+ new Object[] { fCurrentElement.rawname });
+ }
+
+ fDocumentHandler.emptyElement(fElementQName, fAttributes, null);
+
+ if (fBindNamespaces) {
+ fNamespaceContext.popContext();
+ }
+ //pop the element off the stack..
+ fElementStack.popElement(fElementQName);
+ } else {
+ fDocumentHandler.startElement(fElementQName, fAttributes, null);
+ }
+ }
+
+ if (DEBUG_CONTENT_SCANNING)
+ System.out.println("<<< scanStartElement(): " + empty);
+ return empty;
+
+ } // scanStartElement():boolean
+
+ /**
+ * Scans the name of an element in a start or empty tag.
+ *
+ * @see #scanStartElement()
+ */
+ protected void scanStartElementName ()
+ throws IOException, XNIException {
+ // Note: namespace processing is on by default
+ fEntityScanner.scanQName(fElementQName);
+ // Must skip spaces here because the DTD scanner
+ // would consume them at the end of the external subset.
+ fSawSpace = fEntityScanner.skipSpaces();
+ } // scanStartElementName()
+
+ /**
+ * Scans the remainder of a start or empty tag after the element name.
+ *
+ * @see #scanStartElement
+ * @return True if element is empty.
+ */
+ protected boolean scanStartElementAfterName()
+ throws IOException, XNIException {
+
+ // REVISIT - [Q] Why do we need this local variable? -- mrglavas
+ String rawname = fElementQName.rawname;
+ if (fBindNamespaces) {
+ fNamespaceContext.pushContext();
+ if (fScannerState == SCANNER_STATE_ROOT_ELEMENT) {
+ if (fPerformValidation) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XML_DOMAIN,
+ "MSG_GRAMMAR_NOT_FOUND",
+ new Object[] { rawname },
+ XMLErrorReporter.SEVERITY_ERROR);
+
+ if (fDoctypeName == null
+ || !fDoctypeName.equals(rawname)) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XML_DOMAIN,
+ "RootElementTypeMustMatchDoctypedecl",
+ new Object[] { fDoctypeName, rawname },
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ }
+ }
+
+ // push element stack
+ fCurrentElement = fElementStack.pushElement(fElementQName);
+
+ // attributes
+ boolean empty = false;
+ fAttributes.removeAllAttributes();
+ do {
+
+ // end tag?
+ int c = fEntityScanner.peekChar();
+ if (c == '>') {
+ fEntityScanner.scanChar();
+ break;
+ } else if (c == '/') {
+ fEntityScanner.scanChar();
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError(
+ "ElementUnterminated",
+ new Object[] { rawname });
+ }
+ empty = true;
+ break;
+ } else if (!isValidNameStartChar(c) || !fSawSpace) {
+ // Second chance. Check if this character is a high
+ // surrogate of a valid name start character.
+ if (!isValidNameStartHighSurrogate(c) || !fSawSpace) {
+ reportFatalError(
+ "ElementUnterminated",
+ new Object[] { rawname });
+ }
+ }
+
+ // attributes
+ scanAttribute(fAttributes);
+
+ // spaces
+ fSawSpace = fEntityScanner.skipSpaces();
+
+ } while (true);
+
+ if (fBindNamespaces) {
+ // REVISIT: is it required? forbit xmlns prefix for element
+ if (fElementQName.prefix == XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementXMLNSPrefix",
+ new Object[] { fElementQName.rawname },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // bind the element
+ String prefix =
+ fElementQName.prefix != null
+ ? fElementQName.prefix
+ : XMLSymbols.EMPTY_STRING;
+ // assign uri to the element
+ fElementQName.uri = fNamespaceContext.getURI(prefix);
+ // make sure that object in the element stack is updated as well
+ fCurrentElement.uri = fElementQName.uri;
+
+ if (fElementQName.prefix == null && fElementQName.uri != null) {
+ fElementQName.prefix = XMLSymbols.EMPTY_STRING;
+ // making sure that the object in the element stack is updated too.
+ fCurrentElement.prefix = XMLSymbols.EMPTY_STRING;
+ }
+ if (fElementQName.prefix != null && fElementQName.uri == null) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementPrefixUnbound",
+ new Object[] {
+ fElementQName.prefix,
+ fElementQName.rawname },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // bind attributes (xmlns are already bound bellow)
+ int length = fAttributes.getLength();
+ for (int i = 0; i < length; i++) {
+ fAttributes.getName(i, fAttributeQName);
+
+ String aprefix =
+ fAttributeQName.prefix != null
+ ? fAttributeQName.prefix
+ : XMLSymbols.EMPTY_STRING;
+ String uri = fNamespaceContext.getURI(aprefix);
+ // REVISIT: try removing the first "if" and see if it is faster.
+ //
+ if (fAttributeQName.uri != null
+ && fAttributeQName.uri == uri) {
+ continue;
+ }
+ if (aprefix != XMLSymbols.EMPTY_STRING) {
+ fAttributeQName.uri = uri;
+ if (uri == null) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributePrefixUnbound",
+ new Object[] {
+ fElementQName.rawname,
+ fAttributeQName.rawname,
+ aprefix },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ fAttributes.setURI(i, uri);
+ }
+ }
+
+ if (length > 1) {
+ QName name = fAttributes.checkDuplicatesNS();
+ if (name != null) {
+ if (name.uri != null) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNSNotUnique",
+ new Object[] {
+ fElementQName.rawname,
+ name.localpart,
+ name.uri },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ } else {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNotUnique",
+ new Object[] {
+ fElementQName.rawname,
+ name.rawname },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ }
+ }
+
+ // call handler
+ if (fDocumentHandler != null) {
+ if (empty) {
+
+ //decrease the markup depth..
+ fMarkupDepth--;
+
+ // check that this element was opened in the same entity
+ if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
+ reportFatalError(
+ "ElementEntityMismatch",
+ new Object[] { fCurrentElement.rawname });
+ }
+
+ fDocumentHandler.emptyElement(fElementQName, fAttributes, null);
+
+ if (fBindNamespaces) {
+ fNamespaceContext.popContext();
+ }
+ //pop the element off the stack..
+ fElementStack.popElement(fElementQName);
+ } else {
+ fDocumentHandler.startElement(fElementQName, fAttributes, null);
+ }
+ }
+
+ if (DEBUG_CONTENT_SCANNING)
+ System.out.println("<<< scanStartElementAfterName(): " + empty);
+ return empty;
+
+ } // scanStartElementAfterName()
+
+ /**
+ * Scans an attribute.
+ *
+ *
+ * [41] Attribute ::= Name Eq AttValue
+ *
+ *
+ * Note: This method assumes that the next
+ * character on the stream is the first character of the attribute
+ * name.
+ *
+ * Note: This method uses the fAttributeQName and
+ * fQName variables. The contents of these variables will be
+ * destroyed.
+ *
+ * @param attributes The attributes list for the scanned attribute.
+ */
+ protected void scanAttribute(XMLAttributesImpl attributes)
+ throws IOException, XNIException {
+ if (DEBUG_CONTENT_SCANNING)
+ System.out.println(">>> scanAttribute()");
+
+ // name
+ fEntityScanner.scanQName(fAttributeQName);
+
+ // equals
+ fEntityScanner.skipSpaces();
+ if (!fEntityScanner.skipChar('=')) {
+ reportFatalError(
+ "EqRequiredInAttribute",
+ new Object[] {
+ fCurrentElement.rawname,
+ fAttributeQName.rawname });
+ }
+ fEntityScanner.skipSpaces();
+
+ // content
+ int attrIndex;
+
+ if (fBindNamespaces) {
+ attrIndex = attributes.getLength();
+ attributes.addAttributeNS(
+ fAttributeQName,
+ XMLSymbols.fCDATASymbol,
+ null);
+ } else {
+ int oldLen = attributes.getLength();
+ attrIndex =
+ attributes.addAttribute(
+ fAttributeQName,
+ XMLSymbols.fCDATASymbol,
+ null);
+
+ // WFC: Unique Att Spec
+ if (oldLen == attributes.getLength()) {
+ reportFatalError(
+ "AttributeNotUnique",
+ new Object[] {
+ fCurrentElement.rawname,
+ fAttributeQName.rawname });
+ }
+ }
+
+ // Scan attribute value and return true if the non-normalized and normalized value are the same
+ boolean isSameNormalizedAttr = scanAttributeValue(this.fTempString, fTempString2,
+ fAttributeQName.rawname, fIsEntityDeclaredVC, fCurrentElement.rawname);
+
+ String value = fTempString.toString();
+ attributes.setValue(attrIndex, value);
+ // If the non-normalized and normalized value are the same, avoid creating a new string.
+ if (!isSameNormalizedAttr) {
+ attributes.setNonNormalizedValue(attrIndex, fTempString2.toString());
+ }
+ attributes.setSpecified(attrIndex, true);
+
+ // record namespace declarations if any.
+ if (fBindNamespaces) {
+
+ String localpart = fAttributeQName.localpart;
+ String prefix =
+ fAttributeQName.prefix != null
+ ? fAttributeQName.prefix
+ : XMLSymbols.EMPTY_STRING;
+ // when it's of form xmlns="..." or xmlns:prefix="...",
+ // it's a namespace declaration. but prefix:xmlns="..." isn't.
+ if (prefix == XMLSymbols.PREFIX_XMLNS
+ || prefix == XMLSymbols.EMPTY_STRING
+ && localpart == XMLSymbols.PREFIX_XMLNS) {
+
+ // get the internalized value of this attribute
+ String uri = fSymbolTable.addSymbol(value);
+
+ // 1. "xmlns" can't be bound to any namespace
+ if (prefix == XMLSymbols.PREFIX_XMLNS
+ && localpart == XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXMLNS",
+ new Object[] { fAttributeQName },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // 2. the namespace for "xmlns" can't be bound to any prefix
+ if (uri == NamespaceContext.XMLNS_URI) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXMLNS",
+ new Object[] { fAttributeQName },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // 3. "xml" can't be bound to any other namespace than it's own
+ if (localpart == XMLSymbols.PREFIX_XML) {
+ if (uri != NamespaceContext.XML_URI) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXML",
+ new Object[] { fAttributeQName },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ // 4. the namespace for "xml" can't be bound to any other prefix
+ else {
+ if (uri == NamespaceContext.XML_URI) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXML",
+ new Object[] { fAttributeQName },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+
+ prefix =
+ localpart != XMLSymbols.PREFIX_XMLNS
+ ? localpart
+ : XMLSymbols.EMPTY_STRING;
+
+ // Declare prefix in context. Removing the association between a prefix and a
+ // namespace name is permitted in XML 1.1, so if the uri value is the empty string,
+ // the prefix is being unbound. -- mrglavas
+ fNamespaceContext.declarePrefix(
+ prefix,
+ uri.length() != 0 ? uri : null);
+ // bind namespace attribute to a namespace
+ attributes.setURI(
+ attrIndex,
+ fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS));
+
+ } else {
+ // attempt to bind attribute
+ if (fAttributeQName.prefix != null) {
+ attributes.setURI(
+ attrIndex,
+ fNamespaceContext.getURI(fAttributeQName.prefix));
+ }
+ }
+ }
+
+ if (DEBUG_CONTENT_SCANNING)
+ System.out.println("<<< scanAttribute()");
+ } // scanAttribute(XMLAttributes)
+
+ /**
+ * Scans an end element.
+ *
+ *
+ * [42] ETag ::= '</' Name S? '>'
+ *
+ *
+ * Note: This method uses the fElementQName variable.
+ * The contents of this variable will be destroyed. The caller should
+ * copy the needed information out of this variable before calling
+ * this method.
+ *
+ * @return The element depth.
+ */
+ protected int scanEndElement() throws IOException, XNIException {
+ if (DEBUG_CONTENT_SCANNING)
+ System.out.println(">>> scanEndElement()");
+
+ // pop context
+ fElementStack.popElement(fElementQName);
+
+ // Take advantage of the fact that next string _should_ be "fElementQName.rawName",
+ //In scanners most of the time is consumed on checks done for XML characters, we can
+ // optimize on it and avoid the checks done for endElement,
+ //we will also avoid symbol table lookup - neeraj.bajaj@sun.com
+
+ // this should work both for namespace processing true or false...
+
+ //REVISIT: if the string is not the same as expected.. we need to do better error handling..
+ //We can skip this for now... In any case if the string doesn't match -- document is not well formed.
+ if (!fEntityScanner.skipString(fElementQName.rawname)) {
+ reportFatalError(
+ "ETagRequired",
+ new Object[] { fElementQName.rawname });
+ }
+
+ // end
+ fEntityScanner.skipSpaces();
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError(
+ "ETagUnterminated",
+ new Object[] { fElementQName.rawname });
+ }
+ fMarkupDepth--;
+
+ //we have increased the depth for two markup "<" characters
+ fMarkupDepth--;
+
+ // check that this element was opened in the same entity
+ if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
+ reportFatalError(
+ "ElementEntityMismatch",
+ new Object[] { fCurrentElement.rawname });
+ }
+
+ // call handler
+ if (fDocumentHandler != null) {
+
+ fDocumentHandler.endElement(fElementQName, null);
+ if (fBindNamespaces) {
+ fNamespaceContext.popContext();
+ }
+
+ }
+
+ return fMarkupDepth;
+
+ } // scanEndElement():int
+
+ public void reset(XMLComponentManager componentManager)
+ throws XMLConfigurationException {
+
+ super.reset(componentManager);
+ fPerformValidation = false;
+ fBindNamespaces = false;
+ }
+
+ /** Creates a content dispatcher. */
+ protected Dispatcher createContentDispatcher() {
+ return new NS11ContentDispatcher();
+ } // createContentDispatcher():Dispatcher
+
+ /**
+ * Dispatcher to handle content scanning.
+ */
+ protected final class NS11ContentDispatcher extends ContentDispatcher {
+ /**
+ * Scan for root element hook. This method is a hook for
+ * subclasses to add code that handles scanning for the root
+ * element. This method will also attempt to remove DTD validator
+ * from the pipeline, if there is no DTD grammar. If DTD validator
+ * is no longer in the pipeline bind namespaces in the scanner.
+ *
+ *
+ * @return True if the caller should stop and return true which
+ * allows the scanner to switch to a new scanning
+ * dispatcher. A return value of false indicates that
+ * the content dispatcher should continue as normal.
+ */
+ protected boolean scanRootElementHook()
+ throws IOException, XNIException {
+
+ if (fExternalSubsetResolver != null && !fSeenDoctypeDecl
+ && !fDisallowDoctype && (fValidation || fLoadExternalDTD)) {
+ scanStartElementName();
+ resolveExternalSubsetAndRead();
+ reconfigurePipeline();
+ if (scanStartElementAfterName()) {
+ setScannerState(SCANNER_STATE_TRAILING_MISC);
+ setDispatcher(fTrailingMiscDispatcher);
+ return true;
+ }
+ }
+ else {
+ reconfigurePipeline();
+ if (scanStartElement()) {
+ setScannerState(SCANNER_STATE_TRAILING_MISC);
+ setDispatcher(fTrailingMiscDispatcher);
+ return true;
+ }
+ }
+ return false;
+
+ } // scanRootElementHook():boolean
+
+ /**
+ * Re-configures pipeline by removing the DTD validator
+ * if no DTD grammar exists. If no validator exists in the
+ * pipeline or there is no DTD grammar, namespace binding
+ * is performed by the scanner in the enclosing class.
+ */
+ private void reconfigurePipeline() {
+ if (fDTDValidator == null) {
+ fBindNamespaces = true;
+ }
+ else if (!fDTDValidator.hasGrammar()) {
+ fBindNamespaces = true;
+ fPerformValidation = fDTDValidator.validate();
+ // re-configure pipeline
+ XMLDocumentSource source = fDTDValidator.getDocumentSource();
+ XMLDocumentHandler handler = fDTDValidator.getDocumentHandler();
+ source.setDocumentHandler(handler);
+ if (handler != null)
+ handler.setDocumentSource(source);
+ fDTDValidator.setDocumentSource(null);
+ fDTDValidator.setDocumentHandler(null);
+ }
+ } // reconfigurePipeline()
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XML11NamespaceBinder.java b/resources/xerces2-j-src/org/apache/xerces/impl/XML11NamespaceBinder.java
new file mode 100644
index 0000000..78835fe
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XML11NamespaceBinder.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+
+/**
+ * This class performs namespace binding on the startElement and endElement
+ * method calls in accordance with Namespaces in XML 1.1. It extends the standard,
+ * Namespace-1.0-compliant binder in order to do this.
+ *
+ * @xerces.internal
+ *
+ * @author Neil Graham, IBM
+ *
+ * @version $Id$
+ */
+public class XML11NamespaceBinder extends XMLNamespaceBinder {
+
+ //
+ // Constants
+ //
+
+ //
+ // Data
+ //
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XML11NamespaceBinder() {
+ } // ()
+ //
+ // Public methods
+ //
+
+ //
+ // Protected methods
+ //
+
+ // returns true iff the given prefix is bound to "" *and*
+ // this is disallowed by the version of XML namespaces in use.
+ protected boolean prefixBoundToNullURI(String uri, String localpart) {
+ return false;
+ } // prefixBoundToNullURI(String, String): boolean
+
+} // class XML11NamespaceBinder
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XMLDTDScannerImpl.java b/resources/xerces2-j-src/org/apache/xerces/impl/XMLDTDScannerImpl.java
new file mode 100644
index 0000000..1a2d530
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XMLDTDScannerImpl.java
@@ -0,0 +1,2138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.io.IOException;
+
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.util.XMLStringBuffer;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.XMLDTDContentModelHandler;
+import org.apache.xerces.xni.XMLDTDHandler;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLComponent;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLDTDScanner;
+import org.apache.xerces.xni.parser.XMLInputSource;
+
+/**
+ * This class is responsible for scanning the declarations found
+ * in the internal and external subsets of a DTD in an XML document.
+ * The scanner acts as the sources for the DTD information which is
+ * communicated to the DTD handlers.
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/validation
+ * - http://apache.org/xml/features/scanner/notify-char-refs
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/entity-manager
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Arnaud Le Hors, IBM
+ * @author Andy Clark, IBM
+ * @author Glenn Marcy, IBM
+ * @author Eric Ye, IBM
+ *
+ * @version $Id$
+ */
+public class XMLDTDScannerImpl
+ extends XMLScanner
+ implements XMLDTDScanner, XMLComponent, XMLEntityHandler {
+
+ //
+ // Constants
+ //
+
+ // scanner states
+
+ /** Scanner state: end of input. */
+ protected static final int SCANNER_STATE_END_OF_INPUT = 0;
+
+ /** Scanner state: text declaration. */
+ protected static final int SCANNER_STATE_TEXT_DECL = 1;
+
+ /** Scanner state: markup declaration. */
+ protected static final int SCANNER_STATE_MARKUP_DECL = 2;
+
+ // recognized features and properties
+
+ /** Recognized features. */
+ private static final String[] RECOGNIZED_FEATURES = {
+ VALIDATION,
+ NOTIFY_CHAR_REFS,
+ };
+
+ /** Feature defaults. */
+ private static final Boolean[] FEATURE_DEFAULTS = {
+ null,
+ Boolean.FALSE,
+ };
+
+ /** Recognized properties. */
+ private static final String[] RECOGNIZED_PROPERTIES = {
+ SYMBOL_TABLE,
+ ERROR_REPORTER,
+ ENTITY_MANAGER,
+ };
+
+ /** Property defaults. */
+ private static final Object[] PROPERTY_DEFAULTS = {
+ null,
+ null,
+ null,
+ };
+
+ // debugging
+
+ /** Debug scanner state. */
+ private static final boolean DEBUG_SCANNER_STATE = false;
+
+ //
+ // Data
+ //
+
+ // handlers
+
+ /** DTD handler. */
+ protected XMLDTDHandler fDTDHandler;
+
+ /** DTD content model handler. */
+ protected XMLDTDContentModelHandler fDTDContentModelHandler;
+
+ // state
+
+ /** Scanner state. */
+ protected int fScannerState;
+
+ /** Standalone. */
+ protected boolean fStandalone;
+
+ /** Seen external DTD. */
+ protected boolean fSeenExternalDTD;
+
+ /** Seen a parameter entity reference. */
+ protected boolean fSeenPEReferences;
+
+ // private data
+
+ /** Start DTD called. */
+ private boolean fStartDTDCalled;
+
+ /**
+ * Stack of content operators (either '|' or ',') in children
+ * content.
+ */
+ private int[] fContentStack = new int[5];
+
+ /** Size of content stack. */
+ private int fContentDepth;
+
+ /** Parameter entity stack to check well-formedness. */
+ private int[] fPEStack = new int[5];
+
+
+ /** Parameter entity stack to report start/end entity calls. */
+ private boolean[] fPEReport = new boolean[5];
+
+ /** Number of opened parameter entities. */
+ private int fPEDepth;
+
+ /** Markup depth. */
+ private int fMarkUpDepth;
+
+ /** Number of opened external entities. */
+ private int fExtEntityDepth;
+
+ /** Number of opened include sections. */
+ private int fIncludeSectDepth;
+
+ // temporary variables
+
+ /** Array of 3 strings. */
+ private final String[] fStrings = new String[3];
+
+ /** String. */
+ private final XMLString fString = new XMLString();
+
+ /** String buffer. */
+ private final XMLStringBuffer fStringBuffer = new XMLStringBuffer();
+
+ /** String buffer. */
+ private final XMLStringBuffer fStringBuffer2 = new XMLStringBuffer();
+
+ /** Literal text. */
+ private final XMLString fLiteral = new XMLString();
+
+ /** Literal text. */
+ private final XMLString fLiteral2 = new XMLString();
+
+ /** Enumeration values. */
+ private String[] fEnumeration = new String[5];
+
+ /** Enumeration values count. */
+ private int fEnumerationCount;
+
+ /** Ignore conditional section buffer. */
+ private final XMLStringBuffer fIgnoreConditionalBuffer = new XMLStringBuffer(128);
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XMLDTDScannerImpl() {} // ()
+
+ /** Constructor for he use of non-XMLComponentManagers. */
+ public XMLDTDScannerImpl(SymbolTable symbolTable,
+ XMLErrorReporter errorReporter, XMLEntityManager entityManager) {
+ fSymbolTable = symbolTable;
+ fErrorReporter = errorReporter;
+ fEntityManager = entityManager;
+ entityManager.setProperty(SYMBOL_TABLE, fSymbolTable);
+ }
+
+ //
+ // XMLDTDScanner methods
+ //
+
+ /**
+ * Sets the input source.
+ *
+ * @param inputSource The input source or null.
+ *
+ * @throws IOException Thrown on i/o error.
+ */
+ public void setInputSource(XMLInputSource inputSource) throws IOException {
+ if (inputSource == null) {
+ // no system id was available
+ if (fDTDHandler != null) {
+ fDTDHandler.startDTD(null, null);
+ fDTDHandler.endDTD(null);
+ }
+ return;
+ }
+ fEntityManager.setEntityHandler(this);
+ fEntityManager.startDTDEntity(inputSource);
+ } // setInputSource(XMLInputSource)
+
+ /**
+ * Scans the external subset of the document.
+ *
+ * @param complete True if the scanner should scan the document
+ * completely, pushing all events to the registered
+ * document handler. A value of false indicates that
+ * that the scanner should only scan the next portion
+ * of the document and return. A scanner instance is
+ * permitted to completely scan a document if it does
+ * not support this "pull" scanning model.
+ *
+ * @return True if there is more to scan, false otherwise.
+ */
+ public boolean scanDTDExternalSubset(boolean complete)
+ throws IOException, XNIException {
+
+ fEntityManager.setEntityHandler(this);
+ if (fScannerState == SCANNER_STATE_TEXT_DECL) {
+ fSeenExternalDTD = true;
+ boolean textDecl = scanTextDecl();
+ if (fScannerState == SCANNER_STATE_END_OF_INPUT) {
+ return false;
+ }
+ else {
+ // next state is markup decls regardless of whether there
+ // is a TextDecl or not
+ setScannerState(SCANNER_STATE_MARKUP_DECL);
+ if (textDecl && !complete) {
+ return true;
+ }
+ }
+ }
+ // keep dispatching "events"
+ do {
+ if (!scanDecls(complete)) {
+ return false;
+ }
+ } while (complete);
+
+ // return that there is more to scan
+ return true;
+
+ } // scanDTDExternalSubset(boolean):boolean
+
+ /**
+ * Scans the internal subset of the document.
+ *
+ * @param complete True if the scanner should scan the document
+ * completely, pushing all events to the registered
+ * document handler. A value of false indicates that
+ * that the scanner should only scan the next portion
+ * of the document and return. A scanner instance is
+ * permitted to completely scan a document if it does
+ * not support this "pull" scanning model.
+ * @param standalone True if the document was specified as standalone.
+ * This value is important for verifying certain
+ * well-formedness constraints.
+ * @param hasExternalSubset True if the document has an external DTD.
+ * This allows the scanner to properly notify
+ * the handler of the end of the DTD in the
+ * absence of an external subset.
+ *
+ * @return True if there is more to scan, false otherwise.
+ */
+ public boolean scanDTDInternalSubset(boolean complete, boolean standalone,
+ boolean hasExternalSubset)
+ throws IOException, XNIException {
+ // reset entity scanner
+ fEntityScanner = fEntityManager.getEntityScanner();
+ fEntityManager.setEntityHandler(this);
+ fStandalone = standalone;
+ if (fScannerState == SCANNER_STATE_TEXT_DECL) {
+ // call handler
+ if (fDTDHandler != null) {
+ fDTDHandler.startDTD(fEntityScanner, null);
+ fStartDTDCalled = true;
+ }
+ // set starting state for internal subset
+ setScannerState(SCANNER_STATE_MARKUP_DECL);
+ }
+ // keep dispatching "events"
+ do {
+ if (!scanDecls(complete)) {
+ // call handler
+ if (fDTDHandler != null && hasExternalSubset == false) {
+ fDTDHandler.endDTD(null);
+ }
+ // we're done, set starting state for external subset
+ setScannerState(SCANNER_STATE_TEXT_DECL);
+ return false;
+ }
+ } while (complete);
+
+ // return that there is more to scan
+ return true;
+
+ } // scanDTDInternalSubset(boolean,boolean,boolean):boolean
+
+ //
+ // XMLComponent methods
+ //
+
+ /**
+ * reset
+ *
+ * @param componentManager
+ */
+ public void reset(XMLComponentManager componentManager)
+ throws XMLConfigurationException {
+
+ super.reset(componentManager);
+ init();
+
+ } // reset(XMLComponentManager)
+
+ // this is made for something like XMLDTDLoader--XMLComponentManager-free operation...
+ public void reset() {
+ super.reset();
+ init();
+ }
+
+ /**
+ * Returns a list of feature identifiers that are recognized by
+ * this component. This method may return null if no features
+ * are recognized by this component.
+ */
+ public String[] getRecognizedFeatures() {
+ return (String[])(RECOGNIZED_FEATURES.clone());
+ } // getRecognizedFeatures():String[]
+
+ /**
+ * Returns a list of property identifiers that are recognized by
+ * this component. This method may return null if no properties
+ * are recognized by this component.
+ */
+ public String[] getRecognizedProperties() {
+ return (String[])(RECOGNIZED_PROPERTIES.clone());
+ } // getRecognizedProperties():String[]
+
+ /**
+ * Returns the default state for a feature, or null if this
+ * component does not want to report a default value for this
+ * feature.
+ *
+ * @param featureId The feature identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Boolean getFeatureDefault(String featureId) {
+ for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
+ if (RECOGNIZED_FEATURES[i].equals(featureId)) {
+ return FEATURE_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getFeatureDefault(String):Boolean
+
+ /**
+ * Returns the default state for a property, or null if this
+ * component does not want to report a default value for this
+ * property.
+ *
+ * @param propertyId The property identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Object getPropertyDefault(String propertyId) {
+ for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
+ if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
+ return PROPERTY_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getPropertyDefault(String):Object
+
+ //
+ // XMLDTDSource methods
+ //
+
+ /**
+ * setDTDHandler
+ *
+ * @param dtdHandler
+ */
+ public void setDTDHandler(XMLDTDHandler dtdHandler) {
+ fDTDHandler = dtdHandler;
+ } // setDTDHandler(XMLDTDHandler)
+
+ /**
+ * getDTDHandler
+ *
+ * @return the XMLDTDHandler
+ */
+ public XMLDTDHandler getDTDHandler() {
+ return fDTDHandler;
+ } // getDTDHandler(): XMLDTDHandler
+
+ //
+ // XMLDTDContentModelSource methods
+ //
+
+ /**
+ * setDTDContentModelHandler
+ *
+ * @param dtdContentModelHandler
+ */
+ public void setDTDContentModelHandler(XMLDTDContentModelHandler
+ dtdContentModelHandler) {
+ fDTDContentModelHandler = dtdContentModelHandler;
+ } // setDTDContentModelHandler
+
+ /**
+ * getDTDContentModelHandler
+ *
+ * @return XMLDTDContentModelHandler
+ */
+ public XMLDTDContentModelHandler getDTDContentModelHandler() {
+ return fDTDContentModelHandler ;
+ } // setDTDContentModelHandler
+
+ //
+ // XMLEntityHandler methods
+ //
+
+ /**
+ * This method notifies of the start of an entity. The DTD has the
+ * pseudo-name of "[dtd]" parameter entity names start with '%'; and
+ * general entities are just specified by their name.
+ *
+ * @param name The name of the entity.
+ * @param identifier The resource identifier.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal entities or a document entity that is
+ * parsed from a java.io.Reader).
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startEntity(String name,
+ XMLResourceIdentifier identifier,
+ String encoding, Augmentations augs) throws XNIException {
+
+ super.startEntity(name, identifier, encoding, augs);
+
+ boolean dtdEntity = name.equals("[dtd]");
+ if (dtdEntity) {
+ // call handler
+ if (fDTDHandler != null && !fStartDTDCalled ) {
+ fDTDHandler.startDTD(fEntityScanner, null);
+ }
+ if (fDTDHandler != null) {
+ fDTDHandler.startExternalSubset(identifier,null);
+ }
+ fEntityManager.startExternalSubset();
+ fExtEntityDepth++;
+ }
+ else if (name.charAt(0) == '%') {
+ pushPEStack(fMarkUpDepth, fReportEntity);
+ if (fEntityScanner.isExternal()) {
+ fExtEntityDepth++;
+ }
+ }
+
+ // call handler
+ if (fDTDHandler != null && !dtdEntity && fReportEntity) {
+ fDTDHandler.startParameterEntity(name, identifier, encoding, augs);
+ }
+
+ } // startEntity(String,XMLResourceIdentifier,String)
+
+ /**
+ * This method notifies the end of an entity. The DTD has the pseudo-name
+ * of "[dtd]" parameter entity names start with '%'; and general entities
+ * are just specified by their name.
+ *
+ * @param name The name of the entity.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endEntity(String name, Augmentations augs)
+ throws XNIException {
+
+ super.endEntity(name, augs);
+
+ // if there is no data after the doctype
+ //
+ if (fScannerState == SCANNER_STATE_END_OF_INPUT)
+ return;
+
+ // Handle end of PE
+ boolean reportEntity = fReportEntity;
+ if (name.startsWith("%")) {
+ reportEntity = peekReportEntity();
+ // check well-formedness of the enity
+ int startMarkUpDepth = popPEStack();
+ // throw fatalError if this entity was incomplete and
+ // was a freestanding decl
+ if(startMarkUpDepth == 0 &&
+ startMarkUpDepth < fMarkUpDepth) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "ILL_FORMED_PARAMETER_ENTITY_WHEN_USED_IN_DECL",
+ new Object[]{ fEntityManager.fCurrentEntity.name},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ if (startMarkUpDepth != fMarkUpDepth) {
+ reportEntity = false;
+ if (fValidation) {
+ // Proper nesting of parameter entities is a Validity Constraint
+ // and must not be enforced when validation is off
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "ImproperDeclarationNesting",
+ new Object[]{ name },
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ if (fEntityScanner.isExternal()) {
+ fExtEntityDepth--;
+ }
+ // call handler
+ if (fDTDHandler != null && reportEntity) {
+ fDTDHandler.endParameterEntity(name, augs);
+ }
+ }
+ // end DTD
+ else if (name.equals("[dtd]")) {
+ if (fIncludeSectDepth != 0) {
+ reportFatalError("IncludeSectUnterminated", null);
+ }
+ fScannerState = SCANNER_STATE_END_OF_INPUT;
+ // call handler
+ fEntityManager.endExternalSubset();
+ if (fDTDHandler != null) {
+ fDTDHandler.endExternalSubset(null);
+ fDTDHandler.endDTD(null);
+ }
+ fExtEntityDepth--;
+ }
+
+ } // endEntity(String)
+
+ // helper methods
+
+ /**
+ * Sets the scanner state.
+ *
+ * @param state The new scanner state.
+ */
+ protected final void setScannerState(int state) {
+
+ fScannerState = state;
+ if (DEBUG_SCANNER_STATE) {
+ System.out.print("### setScannerState: ");
+ System.out.print(getScannerStateName(state));
+ System.out.println();
+ }
+
+ } // setScannerState(int)
+
+ //
+ // Private methods
+ //
+
+ /** Returns the scanner state name. */
+ private static String getScannerStateName(int state) {
+
+ if (DEBUG_SCANNER_STATE) {
+ switch (state) {
+ case SCANNER_STATE_END_OF_INPUT: return "SCANNER_STATE_END_OF_INPUT";
+ case SCANNER_STATE_TEXT_DECL: return "SCANNER_STATE_TEXT_DECL";
+ case SCANNER_STATE_MARKUP_DECL: return "SCANNER_STATE_MARKUP_DECL";
+ }
+ }
+
+ return "??? ("+state+')';
+
+ } // getScannerStateName(int):String
+
+ protected final boolean scanningInternalSubset() {
+ return fExtEntityDepth == 0;
+ }
+
+ /**
+ * start a parameter entity dealing with the textdecl if there is any
+ *
+ * @param name The name of the parameter entity to start (without the '%')
+ * @param literal Whether this is happening within a literal
+ *
+ * @return The name of the parameter entity (with the '%')
+ */
+ protected String startPE(String name, boolean literal)
+ throws IOException, XNIException {
+ int depth = fPEDepth;
+ String pName = "%"+name;
+ if (!fSeenPEReferences) {
+ fSeenPEReferences = true;
+ fEntityManager.notifyHasPEReferences();
+ }
+ if (fValidation && !fEntityManager.isDeclaredEntity(pName)) {
+ fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,"EntityNotDeclared",
+ new Object[]{name}, XMLErrorReporter.SEVERITY_ERROR);
+ }
+ fEntityManager.startEntity(fSymbolTable.addSymbol(pName),
+ literal);
+ // if we actually got a new entity and it's external
+ // parse text decl if there is any
+ if (depth != fPEDepth && fEntityScanner.isExternal()) {
+ scanTextDecl();
+ }
+ return pName;
+ }
+
+ /**
+ * Dispatch an XML "event".
+ *
+ * @return true if a TextDecl was scanned.
+ *
+ * @throws IOException Thrown on i/o error.
+ * @throws XNIException Thrown on parse error.
+ *
+ */
+ protected final boolean scanTextDecl()
+ throws IOException, XNIException {
+
+ // scan XMLDecl
+ boolean textDecl = false;
+ if (fEntityScanner.skipString("starts with "xml". (e.g. xmlfoo)
+ *
+ * @param target The PI target
+ * @param data The string to fill in with the data
+ */
+ protected final void scanPIData(String target, XMLString data)
+ throws IOException, XNIException {
+
+ super.scanPIData(target, data);
+ fMarkUpDepth--;
+
+ // call handler
+ if (fDTDHandler != null) {
+ fDTDHandler.processingInstruction(target, data, null);
+ }
+
+ } // scanPIData(String)
+
+ /**
+ * Scans a comment.
+ *
+ *
+ * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
+ *
+ *
+ * Note: Called after scanning past '<!--'
+ */
+ protected final void scanComment() throws IOException, XNIException {
+
+ fReportEntity = false;
+ scanComment(fStringBuffer);
+ fMarkUpDepth--;
+
+ // call handler
+ if (fDTDHandler != null) {
+ fDTDHandler.comment(fStringBuffer, null);
+ }
+ fReportEntity = true;
+
+ } // scanComment()
+
+ /**
+ * Scans an element declaration
+ *
+ *
+ * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
+ * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
+ *
+ *
+ * Note: Called after scanning past '<!ELEMENT'
+ */
+ protected final void scanElementDecl() throws IOException, XNIException {
+
+ // spaces
+ fReportEntity = false;
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ELEMENTDECL",
+ null);
+ }
+
+ // element name
+ String name = fEntityScanner.scanName();
+ if (name == null) {
+ reportFatalError("MSG_ELEMENT_TYPE_REQUIRED_IN_ELEMENTDECL",
+ null);
+ }
+
+ // spaces
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_CONTENTSPEC_IN_ELEMENTDECL",
+ new Object[]{name});
+ }
+
+ // content model
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.startContentModel(name, null);
+ }
+ String contentModel = null;
+ fReportEntity = true;
+ if (fEntityScanner.skipString("EMPTY")) {
+ contentModel = "EMPTY";
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.empty(null);
+ }
+ }
+ else if (fEntityScanner.skipString("ANY")) {
+ contentModel = "ANY";
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.any(null);
+ }
+ }
+ else {
+ if (!fEntityScanner.skipChar('(')) {
+ reportFatalError("MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN",
+ new Object[]{name});
+ }
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.startGroup(null);
+ }
+ fStringBuffer.clear();
+ fStringBuffer.append('(');
+ fMarkUpDepth++;
+ skipSeparator(false, !scanningInternalSubset());
+
+ // Mixed content model
+ if (fEntityScanner.skipString("#PCDATA")) {
+ scanMixed(name);
+ }
+ else { // children content
+ scanChildren(name);
+ }
+ contentModel = fStringBuffer.toString();
+ }
+
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.endContentModel(null);
+ }
+
+ fReportEntity = false;
+ skipSeparator(false, !scanningInternalSubset());
+ // end
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError("ElementDeclUnterminated", new Object[]{name});
+ }
+ fReportEntity = true;
+ fMarkUpDepth--;
+
+ // call handler
+ if (fDTDHandler != null) {
+ fDTDHandler.elementDecl(name, contentModel, null);
+ }
+
+ } // scanElementDecl()
+
+ /**
+ * scan Mixed content model
+ * This assumes the content model has been parsed up to #PCDATA and
+ * can simply append to fStringBuffer.
+ *
+ * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'
+ * | '(' S? '#PCDATA' S? ')'
+ *
+ *
+ * @param elName The element type name this declaration is about.
+ *
+ * Note: Called after scanning past '(#PCDATA'.
+ */
+ private final void scanMixed(String elName)
+ throws IOException, XNIException {
+
+ String childName = null;
+
+ fStringBuffer.append("#PCDATA");
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.pcdata(null);
+ }
+ skipSeparator(false, !scanningInternalSubset());
+ while (fEntityScanner.skipChar('|')) {
+ fStringBuffer.append('|');
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.separator(XMLDTDContentModelHandler.SEPARATOR_CHOICE,
+ null);
+ }
+ skipSeparator(false, !scanningInternalSubset());
+
+ childName = fEntityScanner.scanName();
+ if (childName == null) {
+ reportFatalError("MSG_ELEMENT_TYPE_REQUIRED_IN_MIXED_CONTENT",
+ new Object[]{elName});
+ }
+ fStringBuffer.append(childName);
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.element(childName, null);
+ }
+ skipSeparator(false, !scanningInternalSubset());
+ }
+ // The following check must be done in a single call (as opposed to one
+ // for ')' and then one for '*') to guarantee that callbacks are
+ // properly nested. We do not want to trigger endEntity too early in
+ // case we cross the boundary of an entity between the two characters.
+ if (fEntityScanner.skipString(")*")) {
+ fStringBuffer.append(")*");
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.endGroup(null);
+ fDTDContentModelHandler.occurrence(XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE,
+ null);
+ }
+ }
+ else if (childName != null) {
+ reportFatalError("MixedContentUnterminated",
+ new Object[]{elName});
+ }
+ else if (fEntityScanner.skipChar(')')){
+ fStringBuffer.append(')');
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.endGroup(null);
+ }
+ }
+ else {
+ reportFatalError("MSG_CLOSE_PAREN_REQUIRED_IN_CHILDREN",
+ new Object[]{elName});
+ }
+ fMarkUpDepth--;
+ // we are done
+ }
+
+ /**
+ * scan children content model
+ * This assumes it can simply append to fStringBuffer.
+ *
+ * [47] children ::= (choice | seq) ('?' | '*' | '+')?
+ * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
+ * [49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')'
+ * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
+ *
+ *
+ * @param elName The element type name this declaration is about.
+ *
+ * Note: Called after scanning past the first open
+ * paranthesis.
+ */
+ private final void scanChildren(String elName)
+ throws IOException, XNIException {
+
+ fContentDepth = 0;
+ pushContentStack(0);
+ int currentOp = 0;
+ int c;
+ while (true) {
+ if (fEntityScanner.skipChar('(')) {
+ fMarkUpDepth++;
+ fStringBuffer.append('(');
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.startGroup(null);
+ }
+ // push current op on stack and reset it
+ pushContentStack(currentOp);
+ currentOp = 0;
+ skipSeparator(false, !scanningInternalSubset());
+ continue;
+ }
+ skipSeparator(false, !scanningInternalSubset());
+ String childName = fEntityScanner.scanName();
+ if (childName == null) {
+ reportFatalError("MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN",
+ new Object[]{elName});
+ return;
+ }
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.element(childName, null);
+ }
+ fStringBuffer.append(childName);
+ c = fEntityScanner.peekChar();
+ if (c == '?' || c == '*' || c == '+') {
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ short oc;
+ if (c == '?') {
+ oc = XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE;
+ }
+ else if (c == '*') {
+ oc = XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE;
+ }
+ else {
+ oc = XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE;
+ }
+ fDTDContentModelHandler.occurrence(oc, null);
+ }
+ fEntityScanner.scanChar();
+ fStringBuffer.append((char)c);
+ }
+ while (true) {
+ skipSeparator(false, !scanningInternalSubset());
+ c = fEntityScanner.peekChar();
+ if (c == ',' && currentOp != '|') {
+ currentOp = c;
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.separator(XMLDTDContentModelHandler.SEPARATOR_SEQUENCE,
+ null);
+ }
+ fEntityScanner.scanChar();
+ fStringBuffer.append(',');
+ break;
+ }
+ else if (c == '|' && currentOp != ',') {
+ currentOp = c;
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.separator(XMLDTDContentModelHandler.SEPARATOR_CHOICE,
+ null);
+ }
+ fEntityScanner.scanChar();
+ fStringBuffer.append('|');
+ break;
+ }
+ else if (c != ')') {
+ reportFatalError("MSG_CLOSE_PAREN_REQUIRED_IN_CHILDREN",
+ new Object[]{elName});
+ }
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.endGroup(null);
+ }
+ // restore previous op
+ currentOp = popContentStack();
+ short oc;
+ // The following checks must be done in a single call (as
+ // opposed to one for ')' and then one for '?', '*', and '+')
+ // to guarantee that callbacks are properly nested. We do not
+ // want to trigger endEntity too early in case we cross the
+ // boundary of an entity between the two characters.
+ if (fEntityScanner.skipString(")?")) {
+ fStringBuffer.append(")?");
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ oc = XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE;
+ fDTDContentModelHandler.occurrence(oc, null);
+ }
+ }
+ else if (fEntityScanner.skipString(")+")) {
+ fStringBuffer.append(")+");
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ oc = XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE;
+ fDTDContentModelHandler.occurrence(oc, null);
+ }
+ }
+ else if (fEntityScanner.skipString(")*")) {
+ fStringBuffer.append(")*");
+ // call handler
+ if (fDTDContentModelHandler != null) {
+ oc = XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE;
+ fDTDContentModelHandler.occurrence(oc, null);
+ }
+ }
+ else {
+ // no occurrence specified
+ fEntityScanner.scanChar();
+ fStringBuffer.append(')');
+ }
+ fMarkUpDepth--;
+ if (fContentDepth == 0) {
+ return;
+ }
+ }
+ skipSeparator(false, !scanningInternalSubset());
+ }
+ }
+
+ /**
+ * Scans an attlist declaration
+ *
+ *
+ * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
+ * [53] AttDef ::= S Name S AttType S DefaultDecl
+ *
+ *
+ * Note: Called after scanning past '<!ATTLIST'
+ */
+ protected final void scanAttlistDecl() throws IOException, XNIException {
+
+ // spaces
+ fReportEntity = false;
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ATTLISTDECL",
+ null);
+ }
+
+ // element name
+ String elName = fEntityScanner.scanName();
+ if (elName == null) {
+ reportFatalError("MSG_ELEMENT_TYPE_REQUIRED_IN_ATTLISTDECL",
+ null);
+ }
+
+ // call handler
+ if (fDTDHandler != null) {
+ fDTDHandler.startAttlist(elName, null);
+ }
+
+ // spaces
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ // no space, is it the end yet?
+ if (fEntityScanner.skipChar('>')) {
+ // yes, stop here
+ // call handler
+ if (fDTDHandler != null) {
+ fDTDHandler.endAttlist(null);
+ }
+ fMarkUpDepth--;
+ return;
+ }
+ else {
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ATTRIBUTE_NAME_IN_ATTDEF",
+ new Object[]{elName});
+ }
+ }
+
+ // definitions
+ while (!fEntityScanner.skipChar('>')) {
+ String name = fEntityScanner.scanName();
+ if (name == null) {
+ reportFatalError("AttNameRequiredInAttDef",
+ new Object[]{elName});
+ }
+ // spaces
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ATTTYPE_IN_ATTDEF",
+ new Object[]{elName, name});
+ }
+ // type
+ String type = scanAttType(elName, name);
+
+ // spaces
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_DEFAULTDECL_IN_ATTDEF",
+ new Object[]{elName, name});
+ }
+
+ // default decl
+ String defaultType = scanAttDefaultDecl(elName, name,
+ type,
+ fLiteral, fLiteral2);
+ // REVISIT: Should we do anything with the non-normalized
+ // default attribute value? -Ac
+ // yes--according to bug 5073. - neilg
+
+ // call handler
+ if (fDTDHandler != null) {
+ String[] enumeration = null;
+ if (fEnumerationCount != 0) {
+ enumeration = new String[fEnumerationCount];
+ System.arraycopy(fEnumeration, 0, enumeration,
+ 0, fEnumerationCount);
+ }
+ // Determine whether the default value to be passed should be null.
+ // REVISIT: should probably check whether fLiteral.ch is null instead. LM.
+ if (defaultType!=null && (defaultType.equals("#REQUIRED") ||
+ defaultType.equals("#IMPLIED"))) {
+ fDTDHandler.attributeDecl(elName, name, type, enumeration,
+ defaultType, null, null, null);
+ }
+ else {
+ fDTDHandler.attributeDecl(elName, name, type, enumeration,
+ defaultType, fLiteral, fLiteral2, null);
+ }
+ }
+ skipSeparator(false, !scanningInternalSubset());
+ }
+
+ // call handler
+ if (fDTDHandler != null) {
+ fDTDHandler.endAttlist(null);
+ }
+ fMarkUpDepth--;
+ fReportEntity = true;
+
+ } // scanAttlistDecl()
+
+ /**
+ * Scans an attribute type definition
+ *
+ *
+ * [54] AttType ::= StringType | TokenizedType | EnumeratedType
+ * [55] StringType ::= 'CDATA'
+ * [56] TokenizedType ::= 'ID'
+ * | 'IDREF'
+ * | 'IDREFS'
+ * | 'ENTITY'
+ * | 'ENTITIES'
+ * | 'NMTOKEN'
+ * | 'NMTOKENS'
+ * [57] EnumeratedType ::= NotationType | Enumeration
+ * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
+ * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
+ *
+ *
+ * Note: Called after scanning past '<!ATTLIST'
+ *
+ * @param elName The element type name this declaration is about.
+ * @param atName The attribute name this declaration is about.
+ */
+ private final String scanAttType(String elName, String atName)
+ throws IOException, XNIException {
+
+ String type = null;
+ fEnumerationCount = 0;
+ /*
+ * Watchout: the order here is important: when a string happens to
+ * be a substring of another string, the longer one needs to be
+ * looked for first!!
+ */
+ if (fEntityScanner.skipString("CDATA")) {
+ type = "CDATA";
+ }
+ else if (fEntityScanner.skipString("IDREFS")) {
+ type = "IDREFS";
+ }
+ else if (fEntityScanner.skipString("IDREF")) {
+ type = "IDREF";
+ }
+ else if (fEntityScanner.skipString("ID")) {
+ type = "ID";
+ }
+ else if (fEntityScanner.skipString("ENTITY")) {
+ type = "ENTITY";
+ }
+ else if (fEntityScanner.skipString("ENTITIES")) {
+ type = "ENTITIES";
+ }
+ else if (fEntityScanner.skipString("NMTOKENS")) {
+ type = "NMTOKENS";
+ }
+ else if (fEntityScanner.skipString("NMTOKEN")) {
+ type = "NMTOKEN";
+ }
+ else if (fEntityScanner.skipString("NOTATION")) {
+ type = "NOTATION";
+ // spaces
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ reportFatalError("MSG_SPACE_REQUIRED_AFTER_NOTATION_IN_NOTATIONTYPE",
+ new Object[]{elName, atName});
+ }
+ // open paren
+ int c = fEntityScanner.scanChar();
+ if (c != '(') {
+ reportFatalError("MSG_OPEN_PAREN_REQUIRED_IN_NOTATIONTYPE",
+ new Object[]{elName, atName});
+ }
+ fMarkUpDepth++;
+ do {
+ skipSeparator(false, !scanningInternalSubset());
+ String aName = fEntityScanner.scanName();
+ if (aName == null) {
+ reportFatalError("MSG_NAME_REQUIRED_IN_NOTATIONTYPE",
+ new Object[]{elName, atName});
+ c = skipInvalidEnumerationValue();
+ if (c == '|') {
+ continue;
+ }
+ break;
+ }
+ ensureEnumerationSize(fEnumerationCount + 1);
+ fEnumeration[fEnumerationCount++] = aName;
+ skipSeparator(false, !scanningInternalSubset());
+ c = fEntityScanner.scanChar();
+ } while (c == '|');
+ if (c != ')') {
+ reportFatalError("NotationTypeUnterminated",
+ new Object[]{elName, atName});
+ }
+ fMarkUpDepth--;
+ }
+ else { // Enumeration
+ type = "ENUMERATION";
+ // open paren
+ int c = fEntityScanner.scanChar();
+ if (c != '(') {
+// "OPEN_PAREN_REQUIRED_BEFORE_ENUMERATION_IN_ATTRDECL",
+ reportFatalError("AttTypeRequiredInAttDef",
+ new Object[]{elName, atName});
+ }
+ fMarkUpDepth++;
+ do {
+ skipSeparator(false, !scanningInternalSubset());
+ String token = fEntityScanner.scanNmtoken();
+ if (token == null) {
+ reportFatalError("MSG_NMTOKEN_REQUIRED_IN_ENUMERATION",
+ new Object[]{elName, atName});
+ c = skipInvalidEnumerationValue();
+ if (c == '|') {
+ continue;
+ }
+ break;
+ }
+ ensureEnumerationSize(fEnumerationCount + 1);
+ fEnumeration[fEnumerationCount++] = token;
+ skipSeparator(false, !scanningInternalSubset());
+ c = fEntityScanner.scanChar();
+ } while (c == '|');
+ if (c != ')') {
+ reportFatalError("EnumerationUnterminated",
+ new Object[]{elName, atName});
+ }
+ fMarkUpDepth--;
+ }
+ return type;
+
+ } // scanAttType():String
+
+
+ /**
+ * Scans an attribute default declaration
+ *
+ *
+ * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
+ *
+ *
+ * @param elName
+ * @param atName The name of the attribute being scanned.
+ * @param type
+ * @param defaultVal The string to fill in with the default value.
+ * @param nonNormalizedDefaultVal
+ */
+ protected final String scanAttDefaultDecl(String elName, String atName,
+ String type,
+ XMLString defaultVal,
+ XMLString nonNormalizedDefaultVal)
+ throws IOException, XNIException {
+
+ String defaultType = null;
+ fString.clear();
+ defaultVal.clear();
+ if (fEntityScanner.skipString("#REQUIRED")) {
+ defaultType = "#REQUIRED";
+ }
+ else if (fEntityScanner.skipString("#IMPLIED")) {
+ defaultType = "#IMPLIED";
+ }
+ else {
+ if (fEntityScanner.skipString("#FIXED")) {
+ defaultType = "#FIXED";
+ // spaces
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ reportFatalError("MSG_SPACE_REQUIRED_AFTER_FIXED_IN_DEFAULTDECL",
+ new Object[]{elName, atName});
+ }
+ }
+ // AttValue
+ boolean isVC = !fStandalone && (fSeenExternalDTD || fSeenPEReferences);
+ scanAttributeValue(defaultVal, nonNormalizedDefaultVal, atName, isVC, elName);
+ }
+ return defaultType;
+
+ } // ScanAttDefaultDecl
+
+ /**
+ * Scans an entity declaration
+ *
+ *
+ * [70] EntityDecl ::= GEDecl | PEDecl
+ * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
+ * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
+ * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
+ * [74] PEDef ::= EntityValue | ExternalID
+ * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
+ * | 'PUBLIC' S PubidLiteral S SystemLiteral
+ * [76] NDataDecl ::= S 'NDATA' S Name
+ *
+ *
+ * Note: Called after scanning past '<!ENTITY'
+ */
+ private final void scanEntityDecl() throws IOException, XNIException {
+
+ boolean isPEDecl = false;
+ boolean sawPERef = false;
+ fReportEntity = false;
+ if (fEntityScanner.skipSpaces()) {
+ if (!fEntityScanner.skipChar('%')) {
+ isPEDecl = false; //
+ }
+ else if (skipSeparator(true, !scanningInternalSubset())) {
+ //
+ isPEDecl = true;
+ }
+ else if (scanningInternalSubset()) {
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_PEDECL",
+ null);
+ isPEDecl = true;
+ }
+ else if (fEntityScanner.peekChar() == '%') {
+ // is legal
+ skipSeparator(false, !scanningInternalSubset());
+ isPEDecl = true;
+ }
+ else {
+ sawPERef = true;
+ }
+ }
+ else if (scanningInternalSubset() || !fEntityScanner.skipChar('%')) {
+ // or
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_ENTITYDECL",
+ null);
+ isPEDecl = false;
+ }
+ else if (fEntityScanner.skipSpaces()) {
+ //
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_PERCENT_IN_PEDECL",
+ null);
+ isPEDecl = false;
+ }
+ else {
+ sawPERef = true;
+ }
+ if (sawPERef) {
+ while (true) {
+ String peName = fEntityScanner.scanName();
+ if (peName == null) {
+ reportFatalError("NameRequiredInPEReference", null);
+ }
+ else if (!fEntityScanner.skipChar(';')) {
+ reportFatalError("SemicolonRequiredInPEReference",
+ new Object[]{peName});
+ }
+ else {
+ startPE(peName, false);
+ }
+ fEntityScanner.skipSpaces();
+ if (!fEntityScanner.skipChar('%'))
+ break;
+ if (!isPEDecl) {
+ if (skipSeparator(true, !scanningInternalSubset())) {
+ isPEDecl = true;
+ break;
+ }
+ isPEDecl = fEntityScanner.skipChar('%');
+ }
+ }
+ }
+
+ // name
+ String name = null;
+ if(fNamespaces) {
+ name = fEntityScanner.scanNCName();
+ } else {
+ name = fEntityScanner.scanName();
+ }
+ if (name == null) {
+ reportFatalError("MSG_ENTITY_NAME_REQUIRED_IN_ENTITYDECL", null);
+ }
+ // spaces
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ if(fNamespaces && fEntityScanner.peekChar() == ':') {
+ fEntityScanner.scanChar();
+ XMLStringBuffer colonName = new XMLStringBuffer(name);
+ colonName.append(':');
+ String str = fEntityScanner.scanName();
+ if (str != null)
+ colonName.append(str);
+ reportFatalError("ColonNotLegalWithNS", new Object[] {colonName.toString()});
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ reportFatalError("MSG_SPACE_REQUIRED_AFTER_ENTITY_NAME_IN_ENTITYDECL",
+ new Object[]{name});
+ }
+ } else {
+ reportFatalError("MSG_SPACE_REQUIRED_AFTER_ENTITY_NAME_IN_ENTITYDECL",
+ new Object[]{name});
+ }
+ }
+
+ // external id
+ scanExternalID(fStrings, false);
+ String systemId = fStrings[0];
+ String publicId = fStrings[1];
+
+ String notation = null;
+ // NDATA
+ boolean sawSpace = skipSeparator(true, !scanningInternalSubset());
+ if (!isPEDecl && fEntityScanner.skipString("NDATA")) {
+ // check whether there was space before NDATA
+ if (!sawSpace) {
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL",
+ new Object[]{name});
+ }
+
+ // spaces
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_UNPARSED_ENTITYDECL",
+ new Object[]{name});
+ }
+ notation = fEntityScanner.scanName();
+ if (notation == null) {
+ reportFatalError("MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL",
+ new Object[]{name});
+ }
+ }
+
+ // count of direct and indirect references to parameter entities in the value of the entity.
+ int paramEntityRefs = 0;
+ // internal entity
+ if (systemId == null) {
+ paramEntityRefs = scanEntityValue(fLiteral, fLiteral2);
+ // since we need it's value anyway, let's snag it so it doesn't get corrupted
+ // if a new load takes place before we store the entity values
+ fStringBuffer.clear();
+ fStringBuffer2.clear();
+ fStringBuffer.append(fLiteral.ch, fLiteral.offset, fLiteral.length);
+ fStringBuffer2.append(fLiteral2.ch, fLiteral2.offset, fLiteral2.length);
+ }
+
+ // skip possible trailing space
+ skipSeparator(false, !scanningInternalSubset());
+
+ // end
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError("EntityDeclUnterminated", new Object[]{name});
+ }
+ fMarkUpDepth--;
+
+ // register entity and make callback
+ if (isPEDecl) {
+ name = "%" + name;
+ }
+ if (systemId != null) {
+ String baseSystemId = fEntityScanner.getBaseSystemId();
+ if (notation != null) {
+ fEntityManager.addUnparsedEntity(name, publicId, systemId, baseSystemId, notation);
+ }
+ else {
+ fEntityManager.addExternalEntity(name, publicId, systemId,
+ baseSystemId);
+ }
+ if (fDTDHandler != null) {
+ fResourceIdentifier.setValues(publicId, systemId, baseSystemId, XMLEntityManager.expandSystemId(systemId, baseSystemId, false));
+ if (notation != null) {
+ fDTDHandler.unparsedEntityDecl(name, fResourceIdentifier,
+ notation, null);
+ }
+ else {
+ fDTDHandler.externalEntityDecl(name, fResourceIdentifier, null);
+ }
+ }
+ }
+ else {
+ fEntityManager.addInternalEntity(name, fStringBuffer.toString(), paramEntityRefs);
+ if (fDTDHandler != null) {
+ fDTDHandler.internalEntityDecl(name, fStringBuffer, fStringBuffer2, null);
+ }
+ }
+ fReportEntity = true;
+
+ } // scanEntityDecl()
+
+ /**
+ * Scans an entity value.
+ *
+ * Note: This method uses fString, fStringBuffer (through
+ * the use of scanCharReferenceValue), and fStringBuffer2, anything in them
+ * at the time of calling is lost.
+ *
+ * @param value The string to fill in with the value.
+ * @param nonNormalizedValue The string to fill in with the
+ * non-normalized value.
+ *
+ * @return Count of direct and indirect references to parameter entities in the value of the entity.
+ */
+ protected final int scanEntityValue(XMLString value,
+ XMLString nonNormalizedValue)
+ throws IOException, XNIException
+ {
+ int quote = fEntityScanner.scanChar();
+ if (quote != '\'' && quote != '"') {
+ reportFatalError("OpenQuoteMissingInDecl", null);
+ }
+ // store at which depth of entities we start
+ int entityDepth = fEntityDepth;
+ // count of direct and indirect references to parameter entities in the value of the entity.
+ int paramEntityRefs = 0;
+
+ XMLString literal = fString;
+ XMLString literal2 = fString;
+ if (fEntityScanner.scanLiteral(quote, fString) != quote) {
+ fStringBuffer.clear();
+ fStringBuffer2.clear();
+ do {
+ fStringBuffer.append(fString);
+ fStringBuffer2.append(fString);
+ if (fEntityScanner.skipChar('&')) {
+ if (fEntityScanner.skipChar('#')) {
+ fStringBuffer2.append("");
+ scanCharReferenceValue(fStringBuffer, fStringBuffer2);
+ }
+ else {
+ fStringBuffer.append('&');
+ fStringBuffer2.append('&');
+ String eName = fEntityScanner.scanName();
+ if (eName == null) {
+ reportFatalError("NameRequiredInReference",
+ null);
+ }
+ else {
+ fStringBuffer.append(eName);
+ fStringBuffer2.append(eName);
+ }
+ if (!fEntityScanner.skipChar(';')) {
+ reportFatalError("SemicolonRequiredInReference",
+ new Object[]{eName});
+ }
+ else {
+ fStringBuffer.append(';');
+ fStringBuffer2.append(';');
+ }
+ }
+ }
+ else if (fEntityScanner.skipChar('%')) {
+ while (true) {
+ fStringBuffer2.append('%');
+ String peName = fEntityScanner.scanName();
+ if (peName == null) {
+ reportFatalError("NameRequiredInPEReference",
+ null);
+ }
+ else if (!fEntityScanner.skipChar(';')) {
+ reportFatalError("SemicolonRequiredInPEReference",
+ new Object[]{peName});
+ }
+ else {
+ if (scanningInternalSubset()) {
+ reportFatalError("PEReferenceWithinMarkup",
+ new Object[]{peName});
+ }
+ fStringBuffer2.append(peName);
+ fStringBuffer2.append(';');
+ }
+ final String pNameWithPct = startPE(peName, true);
+ paramEntityRefs += (fEntityManager.getParamEntityRefCount(pNameWithPct) + 1);
+ // REVISIT: [Q] Why do we skip spaces here? -Ac
+ // REVISIT: This will make returning the non-
+ // normalized value harder. -Ac
+ fEntityScanner.skipSpaces();
+ if (!fEntityScanner.skipChar('%'))
+ break;
+ }
+ }
+ else {
+ int c = fEntityScanner.peekChar();
+ if (XMLChar.isHighSurrogate(c)) {
+ scanSurrogates(fStringBuffer2);
+ }
+ else if (isInvalidLiteral(c)) {
+ reportFatalError("InvalidCharInLiteral",
+ new Object[]{Integer.toHexString(c)});
+ fEntityScanner.scanChar();
+ }
+ // if it's not the delimiting quote or if it is but from a
+ // different entity than the one this literal started from,
+ // simply append the character to our buffer
+ else if (c != quote || entityDepth != fEntityDepth) {
+ fStringBuffer.append((char)c);
+ fStringBuffer2.append((char)c);
+ fEntityScanner.scanChar();
+ }
+ }
+ } while (fEntityScanner.scanLiteral(quote, fString) != quote);
+ fStringBuffer.append(fString);
+ fStringBuffer2.append(fString);
+ literal = fStringBuffer;
+ literal2 = fStringBuffer2;
+ }
+ value.setValues(literal);
+ nonNormalizedValue.setValues(literal2);
+ if (!fEntityScanner.skipChar(quote)) {
+ reportFatalError("CloseQuoteMissingInDecl", null);
+ }
+ return paramEntityRefs;
+ } // scanEntityValue(XMLString,XMLString):int
+
+ /**
+ * Scans a notation declaration
+ *
+ *
+ * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID|PublicID) S? '>'
+ * [83] PublicID ::= 'PUBLIC' S PubidLiteral
+ *
+ *
+ * Note: Called after scanning past '<!NOTATION'
+ */
+ private final void scanNotationDecl() throws IOException, XNIException {
+
+ // spaces
+ fReportEntity = false;
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_NOTATIONDECL",
+ null);
+ }
+
+ // notation name
+ String name = null;
+ if(fNamespaces) {
+ name = fEntityScanner.scanNCName();
+ } else {
+ name = fEntityScanner.scanName();
+ }
+ if (name == null) {
+ reportFatalError("MSG_NOTATION_NAME_REQUIRED_IN_NOTATIONDECL",
+ null);
+ }
+
+ // spaces
+ if (!skipSeparator(true, !scanningInternalSubset())) {
+ // check for invalid ":"
+ if(fNamespaces && fEntityScanner.peekChar() == ':') {
+ fEntityScanner.scanChar();
+ XMLStringBuffer colonName = new XMLStringBuffer(name);
+ colonName.append(':');
+ colonName.append(fEntityScanner.scanName());
+ reportFatalError("ColonNotLegalWithNS", new Object[] {colonName.toString()});
+ skipSeparator(true, !scanningInternalSubset());
+ } else {
+ reportFatalError("MSG_SPACE_REQUIRED_AFTER_NOTATION_NAME_IN_NOTATIONDECL",
+ new Object[]{name});
+ }
+ }
+
+ // external id
+ scanExternalID(fStrings, true);
+ String systemId = fStrings[0];
+ String publicId = fStrings[1];
+ String baseSystemId = fEntityScanner.getBaseSystemId();
+
+ if (systemId == null && publicId == null) {
+ reportFatalError("ExternalIDorPublicIDRequired",
+ new Object[]{name});
+ }
+
+ // skip possible trailing space
+ skipSeparator(false, !scanningInternalSubset());
+
+ // end
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError("NotationDeclUnterminated", new Object[]{name});
+ }
+ fMarkUpDepth--;
+
+ // call handler
+ if (fDTDHandler != null) {
+ fResourceIdentifier.setValues(publicId, systemId, baseSystemId, XMLEntityManager.expandSystemId(systemId, baseSystemId, false));
+ fDTDHandler.notationDecl(name, fResourceIdentifier, null);
+ }
+ fReportEntity = true;
+
+ } // scanNotationDecl()
+
+ /**
+ * Scans a conditional section. If it's a section to ignore the whole
+ * section gets scanned through and this method only returns after the
+ * closing bracket has been found. When it's an include section though, it
+ * returns to let the main loop take care of scanning it. In that case the
+ * end of the section if handled by the main loop (scanDecls).
+ *
+ *
+ * [61] conditionalSect ::= includeSect | ignoreSect
+ * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
+ * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
+ * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
+ * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
+ *
+ *
+ * Note: Called after scanning past '<![' */
+ private final void scanConditionalSect(int currPEDepth)
+ throws IOException, XNIException {
+
+ fReportEntity = false;
+ skipSeparator(false, !scanningInternalSubset());
+
+ if (fEntityScanner.skipString("INCLUDE")) {
+ skipSeparator(false, !scanningInternalSubset());
+ if(currPEDepth != fPEDepth && fValidation) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "INVALID_PE_IN_CONDITIONAL",
+ new Object[]{ fEntityManager.fCurrentEntity.name},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ // call handler
+ if (!fEntityScanner.skipChar('[')) {
+ reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null);
+ }
+
+ if (fDTDHandler != null) {
+ fDTDHandler.startConditional(XMLDTDHandler.CONDITIONAL_INCLUDE,
+ null);
+ }
+ fIncludeSectDepth++;
+ // just stop there and go back to the main loop
+ fReportEntity = true;
+ }
+ else if (fEntityScanner.skipString("IGNORE")) {
+ skipSeparator(false, !scanningInternalSubset());
+ if(currPEDepth != fPEDepth && fValidation) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "INVALID_PE_IN_CONDITIONAL",
+ new Object[]{ fEntityManager.fCurrentEntity.name},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ // call handler
+ if (fDTDHandler != null) {
+ fDTDHandler.startConditional(XMLDTDHandler.CONDITIONAL_IGNORE,
+ null);
+ }
+ if (!fEntityScanner.skipChar('[')) {
+ reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null);
+ }
+ fReportEntity = true;
+ int initialDepth = ++fIncludeSectDepth;
+ if (fDTDHandler != null) {
+ fIgnoreConditionalBuffer.clear();
+ }
+ while (true) {
+ if (fEntityScanner.skipChar('<')) {
+ if (fDTDHandler != null) {
+ fIgnoreConditionalBuffer.append('<');
+ }
+ //
+ // These tests are split so that we handle cases like
+ // '<', etc.
+ //
+ if (fEntityScanner.skipChar(']')) {
+ if (fDTDHandler != null) {
+ fIgnoreConditionalBuffer.append(']');
+ }
+ while (fEntityScanner.skipChar(']')) {
+ /* empty loop body */
+ if (fDTDHandler != null) {
+ fIgnoreConditionalBuffer.append(']');
+ }
+ }
+ if (fEntityScanner.skipChar('>')) {
+ if (fIncludeSectDepth-- == initialDepth) {
+ fMarkUpDepth--;
+ // call handler
+ if (fDTDHandler != null) {
+ fLiteral.setValues(fIgnoreConditionalBuffer.ch, 0,
+ fIgnoreConditionalBuffer.length - 2);
+ fDTDHandler.ignoredCharacters(fLiteral, null);
+ fDTDHandler.endConditional(null);
+ }
+ return;
+ } else if(fDTDHandler != null) {
+ fIgnoreConditionalBuffer.append('>');
+ }
+ }
+ }
+ }
+ else {
+ int c = fEntityScanner.scanChar();
+ if (fScannerState == SCANNER_STATE_END_OF_INPUT) {
+ reportFatalError("IgnoreSectUnterminated", null);
+ return;
+ }
+ if (fDTDHandler != null) {
+ fIgnoreConditionalBuffer.append((char)c);
+ }
+ }
+ }
+ }
+ else {
+ reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null);
+ }
+
+ } // scanConditionalSect()
+
+ /**
+ * Dispatch an XML "event".
+ *
+ * @param complete True if this method is intended to scan
+ * and dispatch as much as possible.
+ *
+ * @return True if there is more to scan.
+ *
+ * @throws IOException Thrown on i/o error.
+ * @throws XNIException Thrown on parse error.
+ *
+ */
+ protected final boolean scanDecls(boolean complete)
+ throws IOException, XNIException {
+
+ skipSeparator(false, true);
+ boolean again = true;
+ while (again && fScannerState == SCANNER_STATE_MARKUP_DECL) {
+ again = complete;
+ if (fEntityScanner.skipChar('<')) {
+ fMarkUpDepth++;
+ if (fEntityScanner.skipChar('?')) {
+ scanPI();
+ }
+ else if (fEntityScanner.skipChar('!')) {
+ if (fEntityScanner.skipChar('-')) {
+ if (!fEntityScanner.skipChar('-')) {
+ reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD",
+ null);
+ } else {
+ scanComment();
+ }
+ }
+ else if (fEntityScanner.skipString("ELEMENT")) {
+ scanElementDecl();
+ }
+ else if (fEntityScanner.skipString("ATTLIST")) {
+ scanAttlistDecl();
+ }
+ else if (fEntityScanner.skipString("ENTITY")) {
+ scanEntityDecl();
+ }
+ else if (fEntityScanner.skipString("NOTATION")) {
+ scanNotationDecl();
+ }
+ else if (fEntityScanner.skipChar('[') &&
+ !scanningInternalSubset()) {
+ scanConditionalSect(fPEDepth);
+ }
+ else {
+ fMarkUpDepth--;
+ reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD",
+ null);
+ }
+ }
+ else {
+ fMarkUpDepth--;
+ reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null);
+ }
+ }
+ else if (fIncludeSectDepth > 0 && fEntityScanner.skipChar(']')) {
+ // end of conditional section?
+ if (!fEntityScanner.skipChar(']')
+ || !fEntityScanner.skipChar('>')) {
+ reportFatalError("IncludeSectUnterminated", null);
+ }
+ // call handler
+ if (fDTDHandler != null) {
+ fDTDHandler.endConditional(null);
+ }
+ // decreaseMarkupDepth();
+ fIncludeSectDepth--;
+ fMarkUpDepth--;
+ }
+ else if (scanningInternalSubset() &&
+ fEntityScanner.peekChar() == ']') {
+ // this is the end of the internal subset, let's stop here
+ return false;
+ }
+ else if (fEntityScanner.skipSpaces()) {
+ // simply skip
+ }
+ else {
+ reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null);
+ // Skip the part in error
+ int ch;
+ do {
+ // Ignore the current character
+ fEntityScanner.scanChar();
+ // Skip any separators
+ skipSeparator(false, true);
+ // Keeping getting the next character,
+ // until it's one of the expected ones
+ ch = fEntityScanner.peekChar();
+ } while (ch != '<' && ch != ']' && !XMLChar.isSpace(ch));
+ }
+ skipSeparator(false, true);
+ }
+ return fScannerState != SCANNER_STATE_END_OF_INPUT;
+ }
+
+ /**
+ * Skip separator. This is typically just whitespace but it can also be one
+ * or more parameter entity references.
+ *
+ * If there are some it "expands them" by calling the corresponding entity
+ * from the entity manager.
+ *
+ * This is recursive and will process has many refs as possible.
+ *
+ * @param spaceRequired Specify whether some leading whitespace should be
+ * found
+ * @param lookForPERefs Specify whether parameter entity references should
+ * be looked for
+ * @return True if any leading whitespace was found or the end of a
+ * parameter entity was crossed.
+ */
+ private boolean skipSeparator(boolean spaceRequired, boolean lookForPERefs)
+ throws IOException, XNIException
+ {
+ int depth = fPEDepth;
+ boolean sawSpace = fEntityScanner.skipSpaces();
+ if (!lookForPERefs || !fEntityScanner.skipChar('%')) {
+ return !spaceRequired || sawSpace || (depth != fPEDepth);
+ }
+ while (true) {
+ String name = fEntityScanner.scanName();
+ if (name == null) {
+ reportFatalError("NameRequiredInPEReference", null);
+ }
+ else if (!fEntityScanner.skipChar(';')) {
+ reportFatalError("SemicolonRequiredInPEReference",
+ new Object[]{name});
+ }
+ startPE(name, false);
+ fEntityScanner.skipSpaces();
+ if (!fEntityScanner.skipChar('%'))
+ return true;
+ }
+ }
+
+
+ /*
+ * Element Children Content Stack
+ */
+ private final void pushContentStack(int c) {
+ if (fContentStack.length == fContentDepth) {
+ int[] newStack = new int[fContentDepth * 2];
+ System.arraycopy(fContentStack, 0, newStack, 0, fContentDepth);
+ fContentStack = newStack;
+ }
+ fContentStack[fContentDepth++] = c;
+ }
+
+ private final int popContentStack() {
+ return fContentStack[--fContentDepth];
+ }
+
+
+ /*
+ * Parameter Entity Stack
+ */
+ private final void pushPEStack(int depth, boolean report) {
+ if (fPEStack.length == fPEDepth) {
+ int[] newIntStack = new int[fPEDepth * 2];
+ System.arraycopy(fPEStack, 0, newIntStack, 0, fPEDepth);
+ fPEStack = newIntStack;
+ // report end/start calls
+ boolean[] newBooleanStack = new boolean[fPEDepth * 2];
+ System.arraycopy(fPEReport, 0, newBooleanStack, 0, fPEDepth);
+ fPEReport = newBooleanStack;
+
+ }
+ fPEReport[fPEDepth] = report;
+ fPEStack[fPEDepth++] = depth;
+ }
+
+ /** pop the stack */
+ private final int popPEStack() {
+ return fPEStack[--fPEDepth];
+ }
+
+ /** look at the top of the stack */
+ private final boolean peekReportEntity() {
+ return fPEReport[fPEDepth-1];
+ }
+
+
+ /*
+ * Utility method
+ */
+ private final void ensureEnumerationSize(int size) {
+ if (fEnumeration.length == size) {
+ String[] newEnum = new String[size * 2];
+ System.arraycopy(fEnumeration, 0, newEnum, 0, size);
+ fEnumeration = newEnum;
+ }
+ }
+
+ // private methods
+ private void init() {
+ // reset state related data
+ fStartDTDCalled = false;
+ fExtEntityDepth = 0;
+ fIncludeSectDepth = 0;
+ fMarkUpDepth = 0;
+ fPEDepth = 0;
+
+ fStandalone = false;
+ fSeenExternalDTD = false;
+ fSeenPEReferences = false;
+
+ // set starting state
+ setScannerState(SCANNER_STATE_TEXT_DECL);
+ }
+
+ private int skipInvalidEnumerationValue() throws IOException {
+ int c;
+ do {
+ c = fEntityScanner.scanChar();
+ }
+ while (c != '|' && c != ')');
+ ensureEnumerationSize(fEnumerationCount + 1);
+ fEnumeration[fEnumerationCount++] = XMLSymbols.EMPTY_STRING;
+ return c;
+ }
+
+} // class XMLDTDScannerImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XMLDocumentFragmentScannerImpl.java b/resources/xerces2-j-src/org/apache/xerces/impl/XMLDocumentFragmentScannerImpl.java
new file mode 100644
index 0000000..7b5b447
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XMLDocumentFragmentScannerImpl.java
@@ -0,0 +1,1869 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.io.CharConversionException;
+import java.io.EOFException;
+import java.io.IOException;
+
+import org.apache.xerces.impl.io.MalformedByteSequenceException;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.AugmentationsImpl;
+import org.apache.xerces.util.XMLAttributesImpl;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.util.XMLStringBuffer;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLAttributes;
+import org.apache.xerces.xni.XMLDocumentHandler;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLComponent;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLDocumentScanner;
+import org.apache.xerces.xni.parser.XMLInputSource;
+
+/**
+ * This class is responsible for scanning the structure and content
+ * of document fragments. The scanner acts as the source for the
+ * document information which is communicated to the document handler.
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/validation
+ * - http://apache.org/xml/features/scanner/notify-char-refs
+ * - http://apache.org/xml/features/scanner/notify-builtin-refs
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/entity-manager
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Glenn Marcy, IBM
+ * @author Andy Clark, IBM
+ * @author Arnaud Le Hors, IBM
+ * @author Eric Ye, IBM
+ *
+ * @version $Id$
+ */
+public class XMLDocumentFragmentScannerImpl
+ extends XMLScanner
+ implements XMLDocumentScanner, XMLComponent, XMLEntityHandler {
+
+ //
+ // Constants
+ //
+
+ // scanner states
+
+ /** Scanner state: start of markup. */
+ protected static final int SCANNER_STATE_START_OF_MARKUP = 1;
+
+ /** Scanner state: comment. */
+ protected static final int SCANNER_STATE_COMMENT = 2;
+
+ /** Scanner state: processing instruction. */
+ protected static final int SCANNER_STATE_PI = 3;
+
+ /** Scanner state: DOCTYPE. */
+ protected static final int SCANNER_STATE_DOCTYPE = 4;
+
+ /** Scanner state: root element. */
+ protected static final int SCANNER_STATE_ROOT_ELEMENT = 6;
+
+ /** Scanner state: content. */
+ protected static final int SCANNER_STATE_CONTENT = 7;
+
+ /** Scanner state: reference. */
+ protected static final int SCANNER_STATE_REFERENCE = 8;
+
+ /** Scanner state: end of input. */
+ protected static final int SCANNER_STATE_END_OF_INPUT = 13;
+
+ /** Scanner state: terminated. */
+ protected static final int SCANNER_STATE_TERMINATED = 14;
+
+ /** Scanner state: CDATA section. */
+ protected static final int SCANNER_STATE_CDATA = 15;
+
+ /** Scanner state: Text declaration. */
+ protected static final int SCANNER_STATE_TEXT_DECL = 16;
+
+ // feature identifiers
+
+ /** Feature identifier: namespaces. */
+ protected static final String NAMESPACES =
+ Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
+
+ /** Feature identifier: notify built-in refereces. */
+ protected static final String NOTIFY_BUILTIN_REFS =
+ Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_BUILTIN_REFS_FEATURE;
+
+ // property identifiers
+
+ /** Property identifier: entity resolver. */
+ protected static final String ENTITY_RESOLVER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
+
+ // recognized features and properties
+
+ /** Recognized features. */
+ private static final String[] RECOGNIZED_FEATURES = {
+ NAMESPACES,
+ VALIDATION,
+ NOTIFY_BUILTIN_REFS,
+ NOTIFY_CHAR_REFS,
+ };
+
+ /** Feature defaults. */
+ private static final Boolean[] FEATURE_DEFAULTS = {
+ null,
+ null,
+ Boolean.FALSE,
+ Boolean.FALSE,
+ };
+
+ /** Recognized properties. */
+ private static final String[] RECOGNIZED_PROPERTIES = {
+ SYMBOL_TABLE,
+ ERROR_REPORTER,
+ ENTITY_MANAGER,
+ ENTITY_RESOLVER,
+ };
+
+ /** Property defaults. */
+ private static final Object[] PROPERTY_DEFAULTS = {
+ null,
+ null,
+ null,
+ null,
+ };
+
+ // debugging
+
+ /** Debug scanner state. */
+ private static final boolean DEBUG_SCANNER_STATE = false;
+
+ /** Debug dispatcher. */
+ private static final boolean DEBUG_DISPATCHER = false;
+
+ /** Debug content dispatcher scanning. */
+ protected static final boolean DEBUG_CONTENT_SCANNING = false;
+
+ //
+ // Data
+ //
+
+ // protected data
+
+ /** Document handler. */
+ protected XMLDocumentHandler fDocumentHandler;
+
+ /** Entity stack. */
+ protected int[] fEntityStack = new int[4];
+
+ /** Markup depth. */
+ protected int fMarkupDepth;
+
+ /** Scanner state. */
+ protected int fScannerState;
+
+ /** SubScanner state: inside scanContent method. */
+ protected boolean fInScanContent = false;
+
+ /** has external dtd */
+ protected boolean fHasExternalDTD;
+
+ /** Standalone. */
+ protected boolean fStandalone;
+
+ /** True if [Entity Declared] is a VC; false if it is a WFC. */
+ protected boolean fIsEntityDeclaredVC;
+
+ /** External subset resolver. **/
+ protected ExternalSubsetResolver fExternalSubsetResolver;
+
+ // element information
+
+ /** Current element. */
+ protected QName fCurrentElement;
+
+ /** Element stack. */
+ protected final ElementStack fElementStack = new ElementStack();
+
+ // other info
+
+ /** Document system identifier.
+ * REVISIT: So what's this used for? - NG
+ * protected String fDocumentSystemId;
+ ******/
+
+ // features
+
+ /** Notify built-in references. */
+ protected boolean fNotifyBuiltInRefs = false;
+
+ // dispatchers
+
+ /** Active dispatcher. */
+ protected Dispatcher fDispatcher;
+
+ /** Content dispatcher. */
+ protected final Dispatcher fContentDispatcher = createContentDispatcher();
+
+ // temporary variables
+
+ /** Element QName. */
+ protected final QName fElementQName = new QName();
+
+ /** Attribute QName. */
+ protected final QName fAttributeQName = new QName();
+
+ /** Element attributes. */
+ protected final XMLAttributesImpl fAttributes = new XMLAttributesImpl();
+
+ /** String. */
+ protected final XMLString fTempString = new XMLString();
+
+ /** String. */
+ protected final XMLString fTempString2 = new XMLString();
+
+ /** Array of 3 strings. */
+ private final String[] fStrings = new String[3];
+
+ /** String buffer. */
+ private final XMLStringBuffer fStringBuffer = new XMLStringBuffer();
+
+ /** String buffer. */
+ private final XMLStringBuffer fStringBuffer2 = new XMLStringBuffer();
+
+ /** Another QName. */
+ private final QName fQName = new QName();
+
+ /** Single character array. */
+ private final char[] fSingleChar = new char[1];
+
+ /**
+ * Saw spaces after element name or between attributes.
+ *
+ * This is reserved for the case where scanning of a start element spans
+ * several methods, as is the case when scanning the start of a root element
+ * where a DTD external subset may be read after scanning the element name.
+ */
+ private boolean fSawSpace;
+
+ /** Reusable Augmentations. */
+ private Augmentations fTempAugmentations = null;
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XMLDocumentFragmentScannerImpl() {} // ()
+
+ //
+ // XMLDocumentScanner methods
+ //
+
+ /**
+ * Sets the input source.
+ *
+ * @param inputSource The input source.
+ *
+ * @throws IOException Thrown on i/o error.
+ */
+ public void setInputSource(XMLInputSource inputSource) throws IOException {
+ fEntityManager.setEntityHandler(this);
+ fEntityManager.startEntity("$fragment$", inputSource, false, true);
+ //fDocumentSystemId = fEntityManager.expandSystemId(inputSource.getSystemId());
+ } // setInputSource(XMLInputSource)
+
+ /**
+ * Scans a document.
+ *
+ * @param complete True if the scanner should scan the document
+ * completely, pushing all events to the registered
+ * document handler. A value of false indicates that
+ * that the scanner should only scan the next portion
+ * of the document and return. A scanner instance is
+ * permitted to completely scan a document if it does
+ * not support this "pull" scanning model.
+ *
+ * @return True if there is more to scan, false otherwise.
+ */
+ public boolean scanDocument(boolean complete)
+ throws IOException, XNIException {
+
+ // reset entity scanner
+ fEntityScanner = fEntityManager.getEntityScanner();
+
+ // keep dispatching "events"
+ fEntityManager.setEntityHandler(this);
+ do {
+ if (!fDispatcher.dispatch(complete)) {
+ return false;
+ }
+ } while (complete);
+
+ // return success
+ return true;
+
+ } // scanDocument(boolean):boolean
+
+ //
+ // XMLComponent methods
+ //
+
+ /**
+ * Resets the component. The component can query the component manager
+ * about any features and properties that affect the operation of the
+ * component.
+ *
+ * @param componentManager The component manager.
+ *
+ * @throws SAXException Thrown by component on initialization error.
+ * For example, if a feature or property is
+ * required for the operation of the component, the
+ * component manager may throw a
+ * SAXNotRecognizedException or a
+ * SAXNotSupportedException.
+ */
+ public void reset(XMLComponentManager componentManager)
+ throws XMLConfigurationException {
+
+ super.reset(componentManager);
+
+ // other settings
+ //fDocumentSystemId = null;
+
+ // sax features
+ fAttributes.setNamespaces(fNamespaces);
+
+ // initialize vars
+ fMarkupDepth = 0;
+ fCurrentElement = null;
+ fElementStack.clear();
+ fHasExternalDTD = false;
+ fStandalone = false;
+ fIsEntityDeclaredVC = false;
+ fInScanContent = false;
+
+ // setup dispatcher
+ setScannerState(SCANNER_STATE_CONTENT);
+ setDispatcher(fContentDispatcher);
+
+
+ if (fParserSettings) {
+ // parser settings have changed. reset them.
+
+ // xerces features
+ try {
+ fNotifyBuiltInRefs = componentManager.getFeature(NOTIFY_BUILTIN_REFS);
+ } catch (XMLConfigurationException e) {
+ fNotifyBuiltInRefs = false;
+ }
+
+ // xerces properties
+ try {
+ Object resolver = componentManager.getProperty(ENTITY_RESOLVER);
+ fExternalSubsetResolver = (resolver instanceof ExternalSubsetResolver) ?
+ (ExternalSubsetResolver) resolver : null;
+ }
+ catch (XMLConfigurationException e) {
+ fExternalSubsetResolver = null;
+ }
+ }
+
+ } // reset(XMLComponentManager)
+
+ /**
+ * Returns a list of feature identifiers that are recognized by
+ * this component. This method may return null if no features
+ * are recognized by this component.
+ */
+ public String[] getRecognizedFeatures() {
+ return (String[])(RECOGNIZED_FEATURES.clone());
+ } // getRecognizedFeatures():String[]
+
+ /**
+ * Sets the state of a feature. This method is called by the component
+ * manager any time after reset when a feature changes state.
+ *
+ * Note: Components should silently ignore features
+ * that do not affect the operation of the component.
+ *
+ * @param featureId The feature identifier.
+ * @param state The state of the feature.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setFeature(String featureId, boolean state)
+ throws XMLConfigurationException {
+
+ super.setFeature(featureId, state);
+
+ // Xerces properties
+ if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
+ final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
+ if (suffixLength == Constants.NOTIFY_BUILTIN_REFS_FEATURE.length() &&
+ featureId.endsWith(Constants.NOTIFY_BUILTIN_REFS_FEATURE)) {
+ fNotifyBuiltInRefs = state;
+ }
+ }
+
+ } // setFeature(String,boolean)
+
+ /**
+ * Returns a list of property identifiers that are recognized by
+ * this component. This method may return null if no properties
+ * are recognized by this component.
+ */
+ public String[] getRecognizedProperties() {
+ return (String[])(RECOGNIZED_PROPERTIES.clone());
+ } // getRecognizedProperties():String[]
+
+ /**
+ * Sets the value of a property. This method is called by the component
+ * manager any time after reset when a property changes value.
+ *
+ * Note: Components should silently ignore properties
+ * that do not affect the operation of the component.
+ *
+ * @param propertyId The property identifier.
+ * @param value The value of the property.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setProperty(String propertyId, Object value)
+ throws XMLConfigurationException {
+
+ super.setProperty(propertyId, value);
+
+ // Xerces properties
+ if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
+ final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
+ if (suffixLength == Constants.ENTITY_MANAGER_PROPERTY.length() &&
+ propertyId.endsWith(Constants.ENTITY_MANAGER_PROPERTY)) {
+ fEntityManager = (XMLEntityManager)value;
+ return;
+ }
+ if (suffixLength == Constants.ENTITY_RESOLVER_PROPERTY.length() &&
+ propertyId.endsWith(Constants.ENTITY_RESOLVER_PROPERTY)) {
+ fExternalSubsetResolver = (value instanceof ExternalSubsetResolver) ?
+ (ExternalSubsetResolver) value : null;
+ return;
+ }
+ }
+
+ } // setProperty(String,Object)
+
+ /**
+ * Returns the default state for a feature, or null if this
+ * component does not want to report a default value for this
+ * feature.
+ *
+ * @param featureId The feature identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Boolean getFeatureDefault(String featureId) {
+ for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
+ if (RECOGNIZED_FEATURES[i].equals(featureId)) {
+ return FEATURE_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getFeatureDefault(String):Boolean
+
+ /**
+ * Returns the default state for a property, or null if this
+ * component does not want to report a default value for this
+ * property.
+ *
+ * @param propertyId The property identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Object getPropertyDefault(String propertyId) {
+ for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
+ if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
+ return PROPERTY_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getPropertyDefault(String):Object
+
+ //
+ // XMLDocumentSource methods
+ //
+
+ /**
+ * setDocumentHandler
+ *
+ * @param documentHandler
+ */
+ public void setDocumentHandler(XMLDocumentHandler documentHandler) {
+ fDocumentHandler = documentHandler;
+ } // setDocumentHandler(XMLDocumentHandler)
+
+
+ /** Returns the document handler */
+ public XMLDocumentHandler getDocumentHandler(){
+ return fDocumentHandler;
+ }
+
+ //
+ // XMLEntityHandler methods
+ //
+
+ /**
+ * This method notifies of the start of an entity. The DTD has the
+ * pseudo-name of "[dtd]" parameter entity names start with '%'; and
+ * general entities are just specified by their name.
+ *
+ * @param name The name of the entity.
+ * @param identifier The resource identifier.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal entities or a document entity that is
+ * parsed from a java.io.Reader).
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startEntity(String name,
+ XMLResourceIdentifier identifier,
+ String encoding, Augmentations augs) throws XNIException {
+
+ // keep track of this entity before fEntityDepth is increased
+ if (fEntityDepth == fEntityStack.length) {
+ int[] entityarray = new int[fEntityStack.length * 2];
+ System.arraycopy(fEntityStack, 0, entityarray, 0, fEntityStack.length);
+ fEntityStack = entityarray;
+ }
+ fEntityStack[fEntityDepth] = fMarkupDepth;
+
+ super.startEntity(name, identifier, encoding, augs);
+
+ // WFC: entity declared in external subset in standalone doc
+ if(fStandalone && fEntityManager.isEntityDeclInExternalSubset(name)) {
+ reportFatalError("MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
+ new Object[]{name});
+ }
+
+ // call handler
+ if (fDocumentHandler != null && !fScanningAttribute) {
+ if (!name.equals("[xml]")) {
+ fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
+ }
+ }
+
+ } // startEntity(String,XMLResourceIdentifier,String)
+
+ /**
+ * This method notifies the end of an entity. The DTD has the pseudo-name
+ * of "[dtd]" parameter entity names start with '%'; and general entities
+ * are just specified by their name.
+ *
+ * @param name The name of the entity.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endEntity(String name, Augmentations augs) throws XNIException {
+
+ // flush possible pending output buffer - see scanContent
+ if (fInScanContent && fStringBuffer.length != 0
+ && fDocumentHandler != null) {
+ fDocumentHandler.characters(fStringBuffer, null);
+ fStringBuffer.length = 0; // make sure we know it's been flushed
+ }
+
+ super.endEntity(name, augs);
+
+ // make sure markup is properly balanced
+ if (fMarkupDepth != fEntityStack[fEntityDepth]) {
+ reportFatalError("MarkupEntityMismatch", null);
+ }
+
+ // call handler
+ if (fDocumentHandler != null && !fScanningAttribute) {
+ if (!name.equals("[xml]")) {
+ fDocumentHandler.endGeneralEntity(name, augs);
+ }
+ }
+
+ } // endEntity(String)
+
+ //
+ // Protected methods
+ //
+
+ // dispatcher factory methods
+
+ /** Creates a content dispatcher. */
+ protected Dispatcher createContentDispatcher() {
+ return new FragmentContentDispatcher();
+ } // createContentDispatcher():Dispatcher
+
+ // scanning methods
+
+ /**
+ * Scans an XML or text declaration.
+ *
+ *
+ * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
+ * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
+ * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
+ * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
+ * [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'")
+ * | ('"' ('yes' | 'no') '"'))
+ *
+ * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
+ *
+ *
+ * @param scanningTextDecl True if a text declaration is to
+ * be scanned instead of an XML
+ * declaration.
+ */
+ protected void scanXMLDeclOrTextDecl(boolean scanningTextDecl)
+ throws IOException, XNIException {
+
+ // scan decl
+ super.scanXMLDeclOrTextDecl(scanningTextDecl, fStrings);
+ fMarkupDepth--;
+
+ // pseudo-attribute values
+ String version = fStrings[0];
+ String encoding = fStrings[1];
+ String standalone = fStrings[2];
+
+ // set standalone
+ fStandalone = standalone != null && standalone.equals("yes");
+ fEntityManager.setStandalone(fStandalone);
+
+ // set version on reader
+ fEntityScanner.setXMLVersion(version);
+
+ // call handler
+ if (fDocumentHandler != null) {
+ if (scanningTextDecl) {
+ fDocumentHandler.textDecl(version, encoding, null);
+ }
+ else {
+ fDocumentHandler.xmlDecl(version, encoding, standalone, null);
+ }
+ }
+
+ // set encoding on reader
+ if (encoding != null && !fEntityScanner.fCurrentEntity.isEncodingExternallySpecified()) {
+ fEntityScanner.setEncoding(encoding);
+ }
+
+ } // scanXMLDeclOrTextDecl(boolean)
+
+ /**
+ * Scans a processing data. This is needed to handle the situation
+ * where a document starts with a processing instruction whose
+ * target name starts with "xml". (e.g. xmlfoo)
+ *
+ * @param target The PI target
+ * @param data The string to fill in with the data
+ */
+ protected void scanPIData(String target, XMLString data)
+ throws IOException, XNIException {
+
+ super.scanPIData(target, data);
+ fMarkupDepth--;
+
+ // call handler
+ if (fDocumentHandler != null) {
+ fDocumentHandler.processingInstruction(target, data, null);
+ }
+
+ } // scanPIData(String)
+
+ /**
+ * Scans a comment.
+ *
+ *
+ * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
+ *
+ *
+ * Note: Called after scanning past '<!--'
+ */
+ protected void scanComment() throws IOException, XNIException {
+
+ scanComment(fStringBuffer);
+ fMarkupDepth--;
+
+ // call handler
+ if (fDocumentHandler != null) {
+ fDocumentHandler.comment(fStringBuffer, null);
+ }
+
+ } // scanComment()
+
+ /**
+ * Scans a start element. This method will handle the binding of
+ * namespace information and notifying the handler of the start
+ * of the element.
+ *
+ *
+ * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
+ * [40] STag ::= '<' Name (S Attribute)* S? '>'
+ *
+ *
+ * Note: This method assumes that the leading
+ * '<' character has been consumed.
+ *
+ * Note: This method uses the fElementQName and
+ * fAttributes variables. The contents of these variables will be
+ * destroyed. The caller should copy important information out of
+ * these variables before calling this method.
+ *
+ * @return True if element is empty. (i.e. It matches
+ * production [44].
+ */
+ protected boolean scanStartElement()
+ throws IOException, XNIException {
+ if (DEBUG_CONTENT_SCANNING) System.out.println(">>> scanStartElement()");
+
+ // name
+ if (fNamespaces) {
+ fEntityScanner.scanQName(fElementQName);
+ }
+ else {
+ String name = fEntityScanner.scanName();
+ fElementQName.setValues(null, name, name, null);
+ }
+ String rawname = fElementQName.rawname;
+
+ // push element stack
+ fCurrentElement = fElementStack.pushElement(fElementQName);
+
+ // attributes
+ boolean empty = false;
+ fAttributes.removeAllAttributes();
+ do {
+ // spaces
+ boolean sawSpace = fEntityScanner.skipSpaces();
+
+ // end tag?
+ int c = fEntityScanner.peekChar();
+ if (c == '>') {
+ fEntityScanner.scanChar();
+ break;
+ }
+ else if (c == '/') {
+ fEntityScanner.scanChar();
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError("ElementUnterminated",
+ new Object[]{rawname});
+ }
+ empty = true;
+ break;
+ }
+ else if (!isValidNameStartChar(c) || !sawSpace) {
+ // Second chance. Check if this character is a high
+ // surrogate of a valid name start character.
+ if (!isValidNameStartHighSurrogate(c) || !sawSpace) {
+ reportFatalError("ElementUnterminated",
+ new Object[] { rawname });
+ }
+ }
+
+ // attributes
+ scanAttribute(fAttributes);
+
+ } while (true);
+
+ // call handler
+ if (fDocumentHandler != null) {
+ if (empty) {
+
+ //decrease the markup depth..
+ fMarkupDepth--;
+ // check that this element was opened in the same entity
+ if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
+ reportFatalError("ElementEntityMismatch",
+ new Object[]{fCurrentElement.rawname});
+ }
+
+ fDocumentHandler.emptyElement(fElementQName, fAttributes, null);
+
+ //pop the element off the stack..
+ fElementStack.popElement(fElementQName);
+ }
+ else {
+ fDocumentHandler.startElement(fElementQName, fAttributes, null);
+ }
+ }
+
+ if (DEBUG_CONTENT_SCANNING) System.out.println("<<< scanStartElement(): "+empty);
+ return empty;
+
+ } // scanStartElement():boolean
+
+ /**
+ * Scans the name of an element in a start or empty tag.
+ *
+ * @see #scanStartElement()
+ */
+ protected void scanStartElementName ()
+ throws IOException, XNIException {
+ // name
+ if (fNamespaces) {
+ fEntityScanner.scanQName(fElementQName);
+ }
+ else {
+ String name = fEntityScanner.scanName();
+ fElementQName.setValues(null, name, name, null);
+ }
+ // Must skip spaces here because the DTD scanner
+ // would consume them at the end of the external subset.
+ fSawSpace = fEntityScanner.skipSpaces();
+ } // scanStartElementName()
+
+ /**
+ * Scans the remainder of a start or empty tag after the element name.
+ *
+ * @see #scanStartElement
+ * @return True if element is empty.
+ */
+ protected boolean scanStartElementAfterName()
+ throws IOException, XNIException {
+ String rawname = fElementQName.rawname;
+
+ // push element stack
+ fCurrentElement = fElementStack.pushElement(fElementQName);
+
+ // attributes
+ boolean empty = false;
+ fAttributes.removeAllAttributes();
+ do {
+
+ // end tag?
+ int c = fEntityScanner.peekChar();
+ if (c == '>') {
+ fEntityScanner.scanChar();
+ break;
+ }
+ else if (c == '/') {
+ fEntityScanner.scanChar();
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError("ElementUnterminated",
+ new Object[]{rawname});
+ }
+ empty = true;
+ break;
+ }
+ else if (!isValidNameStartChar(c) || !fSawSpace) {
+ // Second chance. Check if this character is a high
+ // surrogate of a valid name start character.
+ if (!isValidNameStartHighSurrogate(c) || !fSawSpace) {
+ reportFatalError("ElementUnterminated",
+ new Object[] { rawname });
+ }
+ }
+
+ // attributes
+ scanAttribute(fAttributes);
+
+ // spaces
+ fSawSpace = fEntityScanner.skipSpaces();
+
+ } while (true);
+
+ // call handler
+ if (fDocumentHandler != null) {
+ if (empty) {
+
+ //decrease the markup depth..
+ fMarkupDepth--;
+ // check that this element was opened in the same entity
+ if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
+ reportFatalError("ElementEntityMismatch",
+ new Object[]{fCurrentElement.rawname});
+ }
+
+ fDocumentHandler.emptyElement(fElementQName, fAttributes, null);
+
+ //pop the element off the stack..
+ fElementStack.popElement(fElementQName);
+ }
+ else {
+ fDocumentHandler.startElement(fElementQName, fAttributes, null);
+ }
+ }
+
+ if (DEBUG_CONTENT_SCANNING) System.out.println("<<< scanStartElementAfterName(): "+empty);
+ return empty;
+ } // scanStartElementAfterName()
+
+ /**
+ * Scans an attribute.
+ *
+ *
+ * [41] Attribute ::= Name Eq AttValue
+ *
+ *
+ * Note: This method assumes that the next
+ * character on the stream is the first character of the attribute
+ * name.
+ *
+ * Note: This method uses the fAttributeQName and
+ * fQName variables. The contents of these variables will be
+ * destroyed.
+ *
+ * @param attributes The attributes list for the scanned attribute.
+ */
+ protected void scanAttribute(XMLAttributes attributes)
+ throws IOException, XNIException {
+ if (DEBUG_CONTENT_SCANNING) System.out.println(">>> scanAttribute()");
+
+ // name
+ if (fNamespaces) {
+ fEntityScanner.scanQName(fAttributeQName);
+ }
+ else {
+ String name = fEntityScanner.scanName();
+ fAttributeQName.setValues(null, name, name, null);
+ }
+
+ // equals
+ fEntityScanner.skipSpaces();
+ if (!fEntityScanner.skipChar('=')) {
+ reportFatalError("EqRequiredInAttribute",
+ new Object[]{fCurrentElement.rawname,fAttributeQName.rawname});
+ }
+ fEntityScanner.skipSpaces();
+
+ // content
+ int oldLen = attributes.getLength();
+ int attrIndex = attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null);
+
+ // WFC: Unique Att Spec
+ if (oldLen == attributes.getLength()) {
+ reportFatalError("AttributeNotUnique",
+ new Object[]{fCurrentElement.rawname,
+ fAttributeQName.rawname});
+ }
+
+ // Scan attribute value and return true if the un-normalized and normalized value are the same
+ boolean isSameNormalizedAttr = scanAttributeValue(fTempString, fTempString2,
+ fAttributeQName.rawname, fIsEntityDeclaredVC, fCurrentElement.rawname);
+
+ attributes.setValue(attrIndex, fTempString.toString());
+ // If the non-normalized and normalized value are the same, avoid creating a new string.
+ if (!isSameNormalizedAttr) {
+ attributes.setNonNormalizedValue(attrIndex, fTempString2.toString());
+ }
+ attributes.setSpecified(attrIndex, true);
+
+ if (DEBUG_CONTENT_SCANNING) System.out.println("<<< scanAttribute()");
+ } // scanAttribute(XMLAttributes)
+
+ /**
+ * Scans element content.
+ *
+ * @return Returns the next character on the stream.
+ */
+ protected int scanContent() throws IOException, XNIException {
+
+ XMLString content = fTempString;
+ int c = fEntityScanner.scanContent(content);
+ if (c == '\r') {
+ // happens when there is the character reference
+ fEntityScanner.scanChar();
+ fStringBuffer.clear();
+ fStringBuffer.append(fTempString);
+ fStringBuffer.append((char)c);
+ content = fStringBuffer;
+ c = -1;
+ }
+ if (fDocumentHandler != null && content.length > 0) {
+ fDocumentHandler.characters(content, null);
+ }
+
+ if (c == ']' && fTempString.length == 0) {
+ fStringBuffer.clear();
+ fStringBuffer.append((char)fEntityScanner.scanChar());
+ // remember where we are in case we get an endEntity before we
+ // could flush the buffer out - this happens when we're parsing an
+ // entity which ends with a ]
+ fInScanContent = true;
+ //
+ // We work on a single character basis to handle cases such as:
+ // ']]]>' which we might otherwise miss.
+ //
+ if (fEntityScanner.skipChar(']')) {
+ fStringBuffer.append(']');
+ while (fEntityScanner.skipChar(']')) {
+ fStringBuffer.append(']');
+ }
+ if (fEntityScanner.skipChar('>')) {
+ reportFatalError("CDEndInContent", null);
+ }
+ }
+ if (fDocumentHandler != null && fStringBuffer.length != 0) {
+ fDocumentHandler.characters(fStringBuffer, null);
+ }
+ fInScanContent = false;
+ c = -1;
+ }
+ return c;
+
+ } // scanContent():int
+
+
+ /**
+ * Scans a CDATA section.
+ *
+ * Note: This method uses the fTempString and
+ * fStringBuffer variables.
+ *
+ * @param complete True if the CDATA section is to be scanned
+ * completely.
+ *
+ * @return True if CDATA is completely scanned.
+ */
+ protected boolean scanCDATASection(boolean complete)
+ throws IOException, XNIException {
+
+ // call handler
+ if (fDocumentHandler != null) {
+ fDocumentHandler.startCDATA(null);
+ }
+
+ while (true) {
+ fStringBuffer.clear();
+ if (!fEntityScanner.scanData("]]", fStringBuffer)) {
+ if (fDocumentHandler != null && fStringBuffer.length > 0) {
+ fDocumentHandler.characters(fStringBuffer, null);
+ }
+ int brackets = 0;
+ while (fEntityScanner.skipChar(']')) {
+ brackets++;
+ }
+ if (fDocumentHandler != null && brackets > 0) {
+ fStringBuffer.clear();
+ if (brackets > XMLEntityManager.DEFAULT_BUFFER_SIZE) {
+ // Handle large sequences of ']'
+ int chunks = brackets / XMLEntityManager.DEFAULT_BUFFER_SIZE;
+ int remainder = brackets % XMLEntityManager.DEFAULT_BUFFER_SIZE;
+ for (int i = 0; i < XMLEntityManager.DEFAULT_BUFFER_SIZE; i++) {
+ fStringBuffer.append(']');
+ }
+ for (int i = 0; i < chunks; i++) {
+ fDocumentHandler.characters(fStringBuffer, null);
+ }
+ if (remainder != 0) {
+ fStringBuffer.length = remainder;
+ fDocumentHandler.characters(fStringBuffer, null);
+ }
+ }
+ else {
+ for (int i = 0; i < brackets; i++) {
+ fStringBuffer.append(']');
+ }
+ fDocumentHandler.characters(fStringBuffer, null);
+ }
+ }
+ if (fEntityScanner.skipChar('>')) {
+ break;
+ }
+ if (fDocumentHandler != null) {
+ fStringBuffer.clear();
+ fStringBuffer.append("]]");
+ fDocumentHandler.characters(fStringBuffer, null);
+ }
+ }
+ else {
+ if (fDocumentHandler != null) {
+ fDocumentHandler.characters(fStringBuffer, null);
+ }
+ int c = fEntityScanner.peekChar();
+ if (c != -1 && isInvalidLiteral(c)) {
+ if (XMLChar.isHighSurrogate(c)) {
+ fStringBuffer.clear();
+ scanSurrogates(fStringBuffer);
+ if (fDocumentHandler != null) {
+ fDocumentHandler.characters(fStringBuffer, null);
+ }
+ }
+ else {
+ reportFatalError("InvalidCharInCDSect",
+ new Object[]{Integer.toString(c,16)});
+ fEntityScanner.scanChar();
+ }
+ }
+ }
+ }
+ fMarkupDepth--;
+
+ // call handler
+ if (fDocumentHandler != null) {
+ fDocumentHandler.endCDATA(null);
+ }
+
+ return true;
+
+ } // scanCDATASection(boolean):boolean
+
+ /**
+ * Scans an end element.
+ *
+ *
+ * [42] ETag ::= '</' Name S? '>'
+ *
+ *
+ * Note: This method uses the fElementQName variable.
+ * The contents of this variable will be destroyed. The caller should
+ * copy the needed information out of this variable before calling
+ * this method.
+ *
+ * @return The element depth.
+ */
+ protected int scanEndElement() throws IOException, XNIException {
+ if (DEBUG_CONTENT_SCANNING) System.out.println(">>> scanEndElement()");
+
+ fElementStack.popElement(fElementQName) ;
+
+ // Take advantage of the fact that next string _should_ be "fElementQName.rawName",
+ //In scanners most of the time is consumed on checks done for XML characters, we can
+ // optimize on it and avoid the checks done for endElement,
+ //we will also avoid symbol table lookup - neeraj.bajaj@sun.com
+
+ // this should work both for namespace processing true or false...
+
+ //REVISIT: if the string is not the same as expected.. we need to do better error handling..
+ //We can skip this for now... In any case if the string doesn't match -- document is not well formed.
+ if (!fEntityScanner.skipString(fElementQName.rawname)) {
+ reportFatalError("ETagRequired", new Object[]{fElementQName.rawname});
+ }
+
+ // end
+ fEntityScanner.skipSpaces();
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError("ETagUnterminated",
+ new Object[]{fElementQName.rawname});
+ }
+ fMarkupDepth--;
+
+ //we have increased the depth for two markup "<" characters
+ fMarkupDepth--;
+
+ // check that this element was opened in the same entity
+ if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
+ reportFatalError("ElementEntityMismatch",
+ new Object[]{fCurrentElement.rawname});
+ }
+
+ // call handler
+ if (fDocumentHandler != null ) {
+ fDocumentHandler.endElement(fElementQName, null);
+ }
+
+ return fMarkupDepth;
+
+ } // scanEndElement():int
+
+ /**
+ * Scans a character reference.
+ *
+ *
+ * [66] CharRef ::= '' [0-9]+ ';' | '' [0-9a-fA-F]+ ';'
+ *
+ */
+ protected void scanCharReference()
+ throws IOException, XNIException {
+
+ fStringBuffer2.clear();
+ int ch = scanCharReferenceValue(fStringBuffer2, null);
+ fMarkupDepth--;
+ if (ch != -1) {
+ // call handler
+ if (fDocumentHandler != null) {
+ if (fNotifyCharRefs) {
+ fDocumentHandler.startGeneralEntity(fCharRefLiteral, null, null, null);
+ }
+ Augmentations augs = null;
+ if (fValidation && ch <= 0x20) {
+ if (fTempAugmentations != null) {
+ fTempAugmentations.removeAllItems();
+ }
+ else {
+ fTempAugmentations = new AugmentationsImpl();
+ }
+ augs = fTempAugmentations;
+ augs.putItem(Constants.CHAR_REF_PROBABLE_WS, Boolean.TRUE);
+ }
+ fDocumentHandler.characters(fStringBuffer2, augs);
+ if (fNotifyCharRefs) {
+ fDocumentHandler.endGeneralEntity(fCharRefLiteral, null);
+ }
+ }
+ }
+
+ } // scanCharReference()
+
+ /**
+ * Scans an entity reference.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws XNIException Thrown if handler throws exception upon
+ * notification.
+ */
+ protected void scanEntityReference() throws IOException, XNIException {
+
+ // name
+ String name = fEntityScanner.scanName();
+ if (name == null) {
+ reportFatalError("NameRequiredInReference", null);
+ return;
+ }
+
+ // end
+ if (!fEntityScanner.skipChar(';')) {
+ reportFatalError("SemicolonRequiredInReference", new Object []{name});
+ }
+ fMarkupDepth--;
+
+ // handle built-in entities
+ if (name == fAmpSymbol) {
+ handleCharacter('&', fAmpSymbol);
+ }
+ else if (name == fLtSymbol) {
+ handleCharacter('<', fLtSymbol);
+ }
+ else if (name == fGtSymbol) {
+ handleCharacter('>', fGtSymbol);
+ }
+ else if (name == fQuotSymbol) {
+ handleCharacter('"', fQuotSymbol);
+ }
+ else if (name == fAposSymbol) {
+ handleCharacter('\'', fAposSymbol);
+ }
+ // start general entity
+ else if (fEntityManager.isUnparsedEntity(name)) {
+ reportFatalError("ReferenceToUnparsedEntity", new Object[]{name});
+ }
+ else {
+ if (!fEntityManager.isDeclaredEntity(name)) {
+ if (fIsEntityDeclaredVC) {
+ if (fValidation)
+ fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,"EntityNotDeclared",
+ new Object[]{name}, XMLErrorReporter.SEVERITY_ERROR);
+ }
+ else {
+ reportFatalError("EntityNotDeclared", new Object[]{name});
+ }
+ }
+ fEntityManager.startEntity(name, false);
+ }
+
+ } // scanEntityReference()
+
+ // utility methods
+
+ /**
+ * Calls document handler with a single character resulting from
+ * built-in entity resolution.
+ *
+ * @param c
+ * @param entity built-in name
+ */
+ private void handleCharacter(char c, String entity) throws XNIException {
+ if (fDocumentHandler != null) {
+ if (fNotifyBuiltInRefs) {
+ fDocumentHandler.startGeneralEntity(entity, null, null, null);
+ }
+
+ fSingleChar[0] = c;
+ fTempString.setValues(fSingleChar, 0, 1);
+ fDocumentHandler.characters(fTempString, null);
+
+ if (fNotifyBuiltInRefs) {
+ fDocumentHandler.endGeneralEntity(entity, null);
+ }
+ }
+ } // handleCharacter(char)
+
+ /**
+ * Handles the end element. This method will make sure that
+ * the end element name matches the current element and notify
+ * the handler about the end of the element and the end of any
+ * relevent prefix mappings.
+ *
+ * Note: This method uses the fQName variable.
+ * The contents of this variable will be destroyed.
+ *
+ * @param element The element.
+ *
+ * @return The element depth.
+ *
+ * @throws XNIException Thrown if the handler throws a SAX exception
+ * upon notification.
+ *
+ */
+ // REVISIT: need to remove this method. It's not called anymore, because
+ // the handling is done when the end tag is scanned. - SG
+ protected int handleEndElement(QName element, boolean isEmpty)
+ throws XNIException {
+
+ fMarkupDepth--;
+ // check that this element was opened in the same entity
+ if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
+ reportFatalError("ElementEntityMismatch",
+ new Object[]{fCurrentElement.rawname});
+ }
+ // make sure the elements match
+ QName startElement = fQName;
+ fElementStack.popElement(startElement);
+ if (element.rawname != startElement.rawname) {
+ reportFatalError("ETagRequired",
+ new Object[]{startElement.rawname});
+ }
+
+ // bind namespaces
+ if (fNamespaces) {
+ element.uri = startElement.uri;
+ }
+
+ // call handler
+ if (fDocumentHandler != null && !isEmpty) {
+ fDocumentHandler.endElement(element, null);
+ }
+
+ return fMarkupDepth;
+
+ } // callEndElement(QName,boolean):int
+
+ // helper methods
+
+ /**
+ * Sets the scanner state.
+ *
+ * @param state The new scanner state.
+ */
+ protected final void setScannerState(int state) {
+
+ fScannerState = state;
+ if (DEBUG_SCANNER_STATE) {
+ System.out.print("### setScannerState: ");
+ System.out.print(getScannerStateName(state));
+ System.out.println();
+ }
+
+ } // setScannerState(int)
+
+ /**
+ * Sets the dispatcher.
+ *
+ * @param dispatcher The new dispatcher.
+ */
+ protected final void setDispatcher(Dispatcher dispatcher) {
+ fDispatcher = dispatcher;
+ if (DEBUG_DISPATCHER) {
+ System.out.print("%%% setDispatcher: ");
+ System.out.print(getDispatcherName(dispatcher));
+ System.out.println();
+ }
+ }
+
+ //
+ // Private methods
+ //
+
+ /** Returns the scanner state name. */
+ protected String getScannerStateName(int state) {
+
+ switch (state) {
+ case SCANNER_STATE_DOCTYPE: return "SCANNER_STATE_DOCTYPE";
+ case SCANNER_STATE_ROOT_ELEMENT: return "SCANNER_STATE_ROOT_ELEMENT";
+ case SCANNER_STATE_START_OF_MARKUP: return "SCANNER_STATE_START_OF_MARKUP";
+ case SCANNER_STATE_COMMENT: return "SCANNER_STATE_COMMENT";
+ case SCANNER_STATE_PI: return "SCANNER_STATE_PI";
+ case SCANNER_STATE_CONTENT: return "SCANNER_STATE_CONTENT";
+ case SCANNER_STATE_REFERENCE: return "SCANNER_STATE_REFERENCE";
+ case SCANNER_STATE_END_OF_INPUT: return "SCANNER_STATE_END_OF_INPUT";
+ case SCANNER_STATE_TERMINATED: return "SCANNER_STATE_TERMINATED";
+ case SCANNER_STATE_CDATA: return "SCANNER_STATE_CDATA";
+ case SCANNER_STATE_TEXT_DECL: return "SCANNER_STATE_TEXT_DECL";
+ }
+
+ return "??? ("+state+')';
+
+ } // getScannerStateName(int):String
+
+ /** Returns the dispatcher name. */
+ public String getDispatcherName(Dispatcher dispatcher) {
+
+ if (DEBUG_DISPATCHER) {
+ if (dispatcher != null) {
+ String name = dispatcher.getClass().getName();
+ int index = name.lastIndexOf('.');
+ if (index != -1) {
+ name = name.substring(index + 1);
+ index = name.lastIndexOf('$');
+ if (index != -1) {
+ name = name.substring(index + 1);
+ }
+ }
+ return name;
+ }
+ }
+ return "null";
+
+ } // getDispatcherName():String
+
+ //
+ // Classes
+ //
+
+ /**
+ * Element stack. This stack operates without synchronization, error
+ * checking, and it re-uses objects instead of throwing popped items
+ * away.
+ *
+ * @author Andy Clark, IBM
+ */
+ protected static class ElementStack {
+
+ //
+ // Data
+ //
+
+ /** The stack data. */
+ protected QName[] fElements;
+
+ /** The size of the stack. */
+ protected int fSize;
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public ElementStack() {
+ fElements = new QName[10];
+ for (int i = 0; i < fElements.length; i++) {
+ fElements[i] = new QName();
+ }
+ } // ()
+
+ //
+ // Public methods
+ //
+
+ /**
+ * Pushes an element on the stack.
+ *
+ * Note: The QName values are copied into the
+ * stack. In other words, the caller does not orphan
+ * the element to the stack. Also, the QName object returned
+ * is not orphaned to the caller. It should be
+ * considered read-only.
+ *
+ * @param element The element to push onto the stack.
+ *
+ * @return Returns the actual QName object that stores the
+ */
+ public QName pushElement(QName element) {
+ if (fSize == fElements.length) {
+ QName[] array = new QName[fElements.length * 2];
+ System.arraycopy(fElements, 0, array, 0, fSize);
+ fElements = array;
+ for (int i = fSize; i < fElements.length; i++) {
+ fElements[i] = new QName();
+ }
+ }
+ fElements[fSize].setValues(element);
+ return fElements[fSize++];
+ } // pushElement(QName):QName
+
+ /**
+ * Pops an element off of the stack by setting the values of
+ * the specified QName.
+ *
+ * Note: The object returned is not
+ * orphaned to the caller. Therefore, the caller should consider
+ * the object to be read-only.
+ */
+ public void popElement(QName element) {
+ element.setValues(fElements[--fSize]);
+ } // popElement(QName)
+
+ /** Clears the stack without throwing away existing QName objects. */
+ public void clear() {
+ fSize = 0;
+ } // clear()
+
+ } // class ElementStack
+
+ /**
+ * This interface defines an XML "event" dispatching model. Classes
+ * that implement this interface are responsible for scanning parts
+ * of the XML document and dispatching callbacks.
+ *
+ * @xerces.internal
+ *
+ * @author Glenn Marcy, IBM
+ */
+ protected interface Dispatcher {
+
+ //
+ // Dispatcher methods
+ //
+
+ /**
+ * Dispatch an XML "event".
+ *
+ * @param complete True if this dispatcher is intended to scan
+ * and dispatch as much as possible.
+ *
+ * @return True if there is more to dispatch either from this
+ * or a another dispatcher.
+ *
+ * @throws IOException Thrown on i/o error.
+ * @throws XNIException Thrown on parse error.
+ */
+ public boolean dispatch(boolean complete)
+ throws IOException, XNIException;
+
+ } // interface Dispatcher
+
+ /**
+ * Dispatcher to handle content scanning.
+ *
+ * @author Andy Clark, IBM
+ * @author Eric Ye, IBM
+ */
+ protected class FragmentContentDispatcher
+ implements Dispatcher {
+
+ //
+ // Dispatcher methods
+ //
+
+ /**
+ * Dispatch an XML "event".
+ *
+ * @param complete True if this dispatcher is intended to scan
+ * and dispatch as much as possible.
+ *
+ * @return True if there is more to dispatch either from this
+ * or a another dispatcher.
+ *
+ * @throws IOException Thrown on i/o error.
+ * @throws XNIException Thrown on parse error.
+ */
+ public boolean dispatch(boolean complete)
+ throws IOException, XNIException {
+ try {
+ boolean again;
+ do {
+ again = false;
+ switch (fScannerState) {
+ case SCANNER_STATE_CONTENT: {
+ if (fEntityScanner.skipChar('<')) {
+ setScannerState(SCANNER_STATE_START_OF_MARKUP);
+ again = true;
+ }
+ else if (fEntityScanner.skipChar('&')) {
+ setScannerState(SCANNER_STATE_REFERENCE);
+ again = true;
+ }
+ else {
+ do {
+ int c = scanContent();
+ if (c == '<') {
+ fEntityScanner.scanChar();
+ setScannerState(SCANNER_STATE_START_OF_MARKUP);
+ break;
+ }
+ else if (c == '&') {
+ fEntityScanner.scanChar();
+ setScannerState(SCANNER_STATE_REFERENCE);
+ break;
+ }
+ else if (c != -1 && isInvalidLiteral(c)) {
+ if (XMLChar.isHighSurrogate(c)) {
+ // special case: surrogates
+ fStringBuffer.clear();
+ if (scanSurrogates(fStringBuffer)) {
+ // call handler
+ if (fDocumentHandler != null) {
+ fDocumentHandler.characters(fStringBuffer, null);
+ }
+ }
+ }
+ else {
+ reportFatalError("InvalidCharInContent",
+ new Object[] {
+ Integer.toString(c, 16)});
+ fEntityScanner.scanChar();
+ }
+ }
+ } while (complete);
+ }
+ break;
+ }
+ case SCANNER_STATE_START_OF_MARKUP: {
+ fMarkupDepth++;
+ if (fEntityScanner.skipChar('/')) {
+ if (scanEndElement() == 0) {
+ if (elementDepthIsZeroHook()) {
+ return true;
+ }
+ }
+ setScannerState(SCANNER_STATE_CONTENT);
+ }
+ else if (isValidNameStartChar(fEntityScanner.peekChar())) {
+ scanStartElement();
+ setScannerState(SCANNER_STATE_CONTENT);
+ }
+ else if (fEntityScanner.skipChar('!')) {
+ if (fEntityScanner.skipChar('-')) {
+ if (!fEntityScanner.skipChar('-')) {
+ reportFatalError("InvalidCommentStart",
+ null);
+ }
+ setScannerState(SCANNER_STATE_COMMENT);
+ again = true;
+ }
+ else if (fEntityScanner.skipString("[CDATA[")) {
+ setScannerState(SCANNER_STATE_CDATA);
+ again = true;
+ }
+ else if (!scanForDoctypeHook()) {
+ reportFatalError("MarkupNotRecognizedInContent",
+ null);
+ }
+ }
+ else if (fEntityScanner.skipChar('?')) {
+ setScannerState(SCANNER_STATE_PI);
+ again = true;
+ }
+ else if (isValidNameStartHighSurrogate(fEntityScanner.peekChar())) {
+ scanStartElement();
+ setScannerState(SCANNER_STATE_CONTENT);
+ }
+ else {
+ reportFatalError("MarkupNotRecognizedInContent",
+ null);
+ setScannerState(SCANNER_STATE_CONTENT);
+ }
+ break;
+ }
+ case SCANNER_STATE_COMMENT: {
+ scanComment();
+ setScannerState(SCANNER_STATE_CONTENT);
+ break;
+ }
+ case SCANNER_STATE_PI: {
+ scanPI();
+ setScannerState(SCANNER_STATE_CONTENT);
+ break;
+ }
+ case SCANNER_STATE_CDATA: {
+ scanCDATASection(complete);
+ setScannerState(SCANNER_STATE_CONTENT);
+ break;
+ }
+ case SCANNER_STATE_REFERENCE: {
+ fMarkupDepth++;
+ // NOTE: We need to set the state beforehand
+ // because the XMLEntityHandler#startEntity
+ // callback could set the state to
+ // SCANNER_STATE_TEXT_DECL and we don't want
+ // to override that scanner state.
+ setScannerState(SCANNER_STATE_CONTENT);
+ if (fEntityScanner.skipChar('#')) {
+ scanCharReference();
+ }
+ else {
+ scanEntityReference();
+ }
+ break;
+ }
+ case SCANNER_STATE_TEXT_DECL: {
+ // scan text decl
+ if (fEntityScanner.skipString("
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/namespaces
+ * - http://xml.org/sax/features/validation
+ * - http://apache.org/xml/features/nonvalidating/load-external-dtd
+ * - http://apache.org/xml/features/scanner/notify-char-refs
+ * - http://apache.org/xml/features/scanner/notify-builtin-refs
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/entity-manager
+ * - http://apache.org/xml/properties/internal/dtd-scanner
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Glenn Marcy, IBM
+ * @author Andy Clark, IBM
+ * @author Arnaud Le Hors, IBM
+ * @author Eric Ye, IBM
+ *
+ * @version $Id$
+ */
+public class XMLDocumentScannerImpl
+ extends XMLDocumentFragmentScannerImpl {
+
+ //
+ // Constants
+ //
+
+ // scanner states
+
+ /** Scanner state: XML declaration. */
+ protected static final int SCANNER_STATE_XML_DECL = 0;
+
+ /** Scanner state: prolog. */
+ protected static final int SCANNER_STATE_PROLOG = 5;
+
+ /** Scanner state: trailing misc. */
+ protected static final int SCANNER_STATE_TRAILING_MISC = 12;
+
+ /** Scanner state: DTD internal declarations. */
+ protected static final int SCANNER_STATE_DTD_INTERNAL_DECLS = 17;
+
+ /** Scanner state: open DTD external subset. */
+ protected static final int SCANNER_STATE_DTD_EXTERNAL = 18;
+
+ /** Scanner state: DTD external declarations. */
+ protected static final int SCANNER_STATE_DTD_EXTERNAL_DECLS = 19;
+
+ // feature identifiers
+
+ /** Feature identifier: load external DTD. */
+ protected static final String LOAD_EXTERNAL_DTD =
+ Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE;
+
+ /** Feature identifier: load external DTD. */
+ protected static final String DISALLOW_DOCTYPE_DECL_FEATURE =
+ Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
+
+ // property identifiers
+
+ /** Property identifier: DTD scanner. */
+ protected static final String DTD_SCANNER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY;
+
+ /** property identifier: ValidationManager */
+ protected static final String VALIDATION_MANAGER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
+
+ /** property identifier: NamespaceContext */
+ protected static final String NAMESPACE_CONTEXT =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY;
+
+
+
+ // recognized features and properties
+
+ /** Recognized features. */
+ private static final String[] RECOGNIZED_FEATURES = {
+ LOAD_EXTERNAL_DTD,
+ DISALLOW_DOCTYPE_DECL_FEATURE,
+ };
+
+ /** Feature defaults. */
+ private static final Boolean[] FEATURE_DEFAULTS = {
+ Boolean.TRUE,
+ Boolean.FALSE,
+ };
+
+ /** Recognized properties. */
+ private static final String[] RECOGNIZED_PROPERTIES = {
+ DTD_SCANNER,
+ VALIDATION_MANAGER,
+ NAMESPACE_CONTEXT,
+ };
+
+ /** Property defaults. */
+ private static final Object[] PROPERTY_DEFAULTS = {
+ null,
+ null,
+ null,
+ };
+
+ //
+ // Data
+ //
+
+ // properties
+
+ /** DTD scanner. */
+ protected XMLDTDScanner fDTDScanner;
+ /** Validation manager . */
+ protected ValidationManager fValidationManager;
+
+ // protected data
+
+ /** Scanning DTD. */
+ protected boolean fScanningDTD;
+
+ // other info
+
+ /** Doctype name. */
+ protected String fDoctypeName;
+
+ /** Doctype declaration public identifier. */
+ protected String fDoctypePublicId;
+
+ /** Doctype declaration system identifier. */
+ protected String fDoctypeSystemId;
+
+ /** Namespace support. */
+ protected NamespaceContext fNamespaceContext = new NamespaceSupport();
+
+ // features
+
+ /** Load external DTD. */
+ protected boolean fLoadExternalDTD = true;
+
+ /** Disallow doctype declaration. */
+ protected boolean fDisallowDoctype = false;
+
+ // state
+
+ /** Seen doctype declaration. */
+ protected boolean fSeenDoctypeDecl;
+
+ // dispatchers
+
+ /** XML declaration dispatcher. */
+ protected final Dispatcher fXMLDeclDispatcher = new XMLDeclDispatcher();
+
+ /** Prolog dispatcher. */
+ protected final Dispatcher fPrologDispatcher = new PrologDispatcher();
+
+ /** DTD dispatcher. */
+ protected final Dispatcher fDTDDispatcher = new DTDDispatcher();
+
+ /** Trailing miscellaneous section dispatcher. */
+ protected final Dispatcher fTrailingMiscDispatcher = new TrailingMiscDispatcher();
+
+ // temporary variables
+
+ /** Array of 3 strings. */
+ private final String[] fStrings = new String[3];
+
+ /** String. */
+ private final XMLString fString = new XMLString();
+
+ /** String buffer. */
+ private final XMLStringBuffer fStringBuffer = new XMLStringBuffer();
+
+ /** External subset source. */
+ private XMLInputSource fExternalSubsetSource = null;
+
+ /** A DTD Description. */
+ private final XMLDTDDescription fDTDDescription = new XMLDTDDescription(null, null, null, null, null);
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XMLDocumentScannerImpl() {} // ()
+
+ //
+ // XMLDocumentScanner methods
+ //
+
+ /**
+ * Sets the input source.
+ *
+ * @param inputSource The input source.
+ *
+ * @throws IOException Thrown on i/o error.
+ */
+ public void setInputSource(XMLInputSource inputSource) throws IOException {
+ fEntityManager.setEntityHandler(this);
+ fEntityManager.startDocumentEntity(inputSource);
+ //fDocumentSystemId = fEntityManager.expandSystemId(inputSource.getSystemId());
+ } // setInputSource(XMLInputSource)
+
+ //
+ // XMLComponent methods
+ //
+
+ /**
+ * Resets the component. The component can query the component manager
+ * about any features and properties that affect the operation of the
+ * component.
+ *
+ * @param componentManager The component manager.
+ *
+ * @throws SAXException Thrown by component on initialization error.
+ * For example, if a feature or property is
+ * required for the operation of the component, the
+ * component manager may throw a
+ * SAXNotRecognizedException or a
+ * SAXNotSupportedException.
+ */
+ public void reset(XMLComponentManager componentManager)
+ throws XMLConfigurationException {
+
+ super.reset(componentManager);
+
+ // other settings
+ fDoctypeName = null;
+ fDoctypePublicId = null;
+ fDoctypeSystemId = null;
+ fSeenDoctypeDecl = false;
+ fScanningDTD = false;
+ fExternalSubsetSource = null;
+
+ if (!fParserSettings) {
+ // parser settings have not been changed
+ fNamespaceContext.reset();
+ // setup dispatcher
+ setScannerState(SCANNER_STATE_XML_DECL);
+ setDispatcher(fXMLDeclDispatcher);
+ return;
+ }
+
+ // xerces features
+ try {
+ fLoadExternalDTD = componentManager.getFeature(LOAD_EXTERNAL_DTD);
+ }
+ catch (XMLConfigurationException e) {
+ fLoadExternalDTD = true;
+ }
+ try {
+ fDisallowDoctype = componentManager.getFeature(DISALLOW_DOCTYPE_DECL_FEATURE);
+ }
+ catch (XMLConfigurationException e) {
+ fDisallowDoctype = false;
+ }
+
+ // xerces properties
+ fDTDScanner = (XMLDTDScanner)componentManager.getProperty(DTD_SCANNER);
+ try {
+ fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
+ }
+ catch (XMLConfigurationException e) {
+ fValidationManager = null;
+ }
+
+ try {
+ fNamespaceContext = (NamespaceContext)componentManager.getProperty(NAMESPACE_CONTEXT);
+ }
+ catch (XMLConfigurationException e) { }
+ if (fNamespaceContext == null) {
+ fNamespaceContext = new NamespaceSupport();
+ }
+ fNamespaceContext.reset();
+
+ // setup dispatcher
+ setScannerState(SCANNER_STATE_XML_DECL);
+ setDispatcher(fXMLDeclDispatcher);
+
+ } // reset(XMLComponentManager)
+
+ /**
+ * Returns a list of feature identifiers that are recognized by
+ * this component. This method may return null if no features
+ * are recognized by this component.
+ */
+ public String[] getRecognizedFeatures() {
+ String[] featureIds = super.getRecognizedFeatures();
+ int length = featureIds != null ? featureIds.length : 0;
+ String[] combinedFeatureIds = new String[length + RECOGNIZED_FEATURES.length];
+ if (featureIds != null) {
+ System.arraycopy(featureIds, 0, combinedFeatureIds, 0, featureIds.length);
+ }
+ System.arraycopy(RECOGNIZED_FEATURES, 0, combinedFeatureIds, length, RECOGNIZED_FEATURES.length);
+ return combinedFeatureIds;
+ } // getRecognizedFeatures():String[]
+
+ /**
+ * Sets the state of a feature. This method is called by the component
+ * manager any time after reset when a feature changes state.
+ *
+ * Note: Components should silently ignore features
+ * that do not affect the operation of the component.
+ *
+ * @param featureId The feature identifier.
+ * @param state The state of the feature.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setFeature(String featureId, boolean state)
+ throws XMLConfigurationException {
+
+ super.setFeature(featureId, state);
+
+ // Xerces properties
+ if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
+ final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
+
+ if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() &&
+ featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) {
+ fLoadExternalDTD = state;
+ return;
+ }
+ else if (suffixLength == Constants.DISALLOW_DOCTYPE_DECL_FEATURE.length() &&
+ featureId.endsWith(Constants.DISALLOW_DOCTYPE_DECL_FEATURE)) {
+ fDisallowDoctype = state;
+ return;
+ }
+ }
+
+ } // setFeature(String,boolean)
+
+ /**
+ * Returns a list of property identifiers that are recognized by
+ * this component. This method may return null if no properties
+ * are recognized by this component.
+ */
+ public String[] getRecognizedProperties() {
+ String[] propertyIds = super.getRecognizedProperties();
+ int length = propertyIds != null ? propertyIds.length : 0;
+ String[] combinedPropertyIds = new String[length + RECOGNIZED_PROPERTIES.length];
+ if (propertyIds != null) {
+ System.arraycopy(propertyIds, 0, combinedPropertyIds, 0, propertyIds.length);
+ }
+ System.arraycopy(RECOGNIZED_PROPERTIES, 0, combinedPropertyIds, length, RECOGNIZED_PROPERTIES.length);
+ return combinedPropertyIds;
+ } // getRecognizedProperties():String[]
+
+ /**
+ * Sets the value of a property. This method is called by the component
+ * manager any time after reset when a property changes value.
+ *
+ * Note: Components should silently ignore properties
+ * that do not affect the operation of the component.
+ *
+ * @param propertyId The property identifier.
+ * @param value The value of the property.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setProperty(String propertyId, Object value)
+ throws XMLConfigurationException {
+
+ super.setProperty(propertyId, value);
+
+ // Xerces properties
+ if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
+ final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
+
+ if (suffixLength == Constants.DTD_SCANNER_PROPERTY.length() &&
+ propertyId.endsWith(Constants.DTD_SCANNER_PROPERTY)) {
+ fDTDScanner = (XMLDTDScanner)value;
+ }
+ if (suffixLength == Constants.NAMESPACE_CONTEXT_PROPERTY.length() &&
+ propertyId.endsWith(Constants.NAMESPACE_CONTEXT_PROPERTY)) {
+ if (value != null) {
+ fNamespaceContext = (NamespaceContext)value;
+ }
+ }
+
+ return;
+ }
+
+ } // setProperty(String,Object)
+
+ /**
+ * Returns the default state for a feature, or null if this
+ * component does not want to report a default value for this
+ * feature.
+ *
+ * @param featureId The feature identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Boolean getFeatureDefault(String featureId) {
+
+ for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
+ if (RECOGNIZED_FEATURES[i].equals(featureId)) {
+ return FEATURE_DEFAULTS[i];
+ }
+ }
+ return super.getFeatureDefault(featureId);
+ } // getFeatureDefault(String):Boolean
+
+ /**
+ * Returns the default state for a property, or null if this
+ * component does not want to report a default value for this
+ * property.
+ *
+ * @param propertyId The property identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Object getPropertyDefault(String propertyId) {
+ for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
+ if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
+ return PROPERTY_DEFAULTS[i];
+ }
+ }
+ return super.getPropertyDefault(propertyId);
+ } // getPropertyDefault(String):Object
+
+ //
+ // XMLEntityHandler methods
+ //
+
+ /**
+ * This method notifies of the start of an entity. The DTD has the
+ * pseudo-name of "[dtd]" parameter entity names start with '%'; and
+ * general entities are just specified by their name.
+ *
+ * @param name The name of the entity.
+ * @param identifier The resource identifier.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal entities or a document entity that is
+ * parsed from a java.io.Reader).
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startEntity(String name,
+ XMLResourceIdentifier identifier,
+ String encoding, Augmentations augs) throws XNIException {
+
+ super.startEntity(name, identifier, encoding, augs);
+
+ // prepare to look for a TextDecl if external general entity
+ if (!name.equals("[xml]") && fEntityScanner.isExternal()) {
+ setScannerState(SCANNER_STATE_TEXT_DECL);
+ }
+
+ // call handler
+ if (fDocumentHandler != null && name.equals("[xml]")) {
+ fDocumentHandler.startDocument(fEntityScanner, encoding, fNamespaceContext, null);
+ }
+
+ } // startEntity(String,identifier,String)
+
+ /**
+ * This method notifies the end of an entity. The DTD has the pseudo-name
+ * of "[dtd]" parameter entity names start with '%'; and general entities
+ * are just specified by their name.
+ *
+ * @param name The name of the entity.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endEntity(String name, Augmentations augs) throws XNIException {
+
+ super.endEntity(name, augs);
+
+ // call handler
+ if (fDocumentHandler != null && name.equals("[xml]")) {
+ fDocumentHandler.endDocument(null);
+ }
+
+ } // endEntity(String)
+
+ //
+ // Protected methods
+ //
+
+ // dispatcher factory methods
+
+ /** Creates a content dispatcher. */
+ protected Dispatcher createContentDispatcher() {
+ return new ContentDispatcher();
+ } // createContentDispatcher():Dispatcher
+
+ // scanning methods
+
+ /** Scans a doctype declaration. */
+ protected boolean scanDoctypeDecl() throws IOException, XNIException {
+
+ // spaces
+ if (!fEntityScanner.skipSpaces()) {
+ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL",
+ null);
+ }
+
+ // root element name
+ fDoctypeName = fEntityScanner.scanName();
+ if (fDoctypeName == null) {
+ reportFatalError("MSG_ROOT_ELEMENT_TYPE_REQUIRED", null);
+ }
+
+ // external id
+ if (fEntityScanner.skipSpaces()) {
+ scanExternalID(fStrings, false);
+ fDoctypeSystemId = fStrings[0];
+ fDoctypePublicId = fStrings[1];
+ fEntityScanner.skipSpaces();
+ }
+
+ fHasExternalDTD = fDoctypeSystemId != null;
+
+ // Attempt to locate an external subset with an external subset resolver.
+ if (!fHasExternalDTD && fExternalSubsetResolver != null) {
+ fDTDDescription.setValues(null, null, fEntityManager.getCurrentResourceIdentifier().getExpandedSystemId(), null);
+ fDTDDescription.setRootName(fDoctypeName);
+ fExternalSubsetSource = fExternalSubsetResolver.getExternalSubset(fDTDDescription);
+ fHasExternalDTD = fExternalSubsetSource != null;
+ }
+
+ // call handler
+ if (fDocumentHandler != null) {
+ // NOTE: I don't like calling the doctypeDecl callback until
+ // end of the *full* doctype line (including internal
+ // subset) is parsed correctly but SAX2 requires that
+ // it knows the root element name and public and system
+ // identifier for the startDTD call. -Ac
+ if (fExternalSubsetSource == null) {
+ fDocumentHandler.doctypeDecl(fDoctypeName, fDoctypePublicId, fDoctypeSystemId, null);
+ }
+ else {
+ fDocumentHandler.doctypeDecl(fDoctypeName, fExternalSubsetSource.getPublicId(), fExternalSubsetSource.getSystemId(), null);
+ }
+ }
+
+ // is there an internal subset?
+ boolean internalSubset = true;
+ if (!fEntityScanner.skipChar('[')) {
+ internalSubset = false;
+ fEntityScanner.skipSpaces();
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError("DoctypedeclUnterminated", new Object[]{fDoctypeName});
+ }
+ fMarkupDepth--;
+ }
+
+ return internalSubset;
+
+ } // scanDoctypeDecl():boolean
+
+ //
+ // Private methods
+ //
+
+ /** Returns the scanner state name. */
+ protected String getScannerStateName(int state) {
+
+ switch (state) {
+ case SCANNER_STATE_XML_DECL: return "SCANNER_STATE_XML_DECL";
+ case SCANNER_STATE_PROLOG: return "SCANNER_STATE_PROLOG";
+ case SCANNER_STATE_TRAILING_MISC: return "SCANNER_STATE_TRAILING_MISC";
+ case SCANNER_STATE_DTD_INTERNAL_DECLS: return "SCANNER_STATE_DTD_INTERNAL_DECLS";
+ case SCANNER_STATE_DTD_EXTERNAL: return "SCANNER_STATE_DTD_EXTERNAL";
+ case SCANNER_STATE_DTD_EXTERNAL_DECLS: return "SCANNER_STATE_DTD_EXTERNAL_DECLS";
+ }
+ return super.getScannerStateName(state);
+
+ } // getScannerStateName(int):String
+
+ //
+ // Classes
+ //
+
+ /**
+ * Dispatcher to handle XMLDecl scanning.
+ *
+ * @author Andy Clark, IBM
+ */
+ protected final class XMLDeclDispatcher
+ implements Dispatcher {
+
+ //
+ // Dispatcher methods
+ //
+
+ /**
+ * Dispatch an XML "event".
+ *
+ * @param complete True if this dispatcher is intended to scan
+ * and dispatch as much as possible.
+ *
+ * @return True if there is more to dispatch either from this
+ * or a another dispatcher.
+ *
+ * @throws IOException Thrown on i/o error.
+ * @throws XNIException Thrown on parse error.
+ */
+ public boolean dispatch(boolean complete)
+ throws IOException, XNIException {
+
+ // next dispatcher is prolog regardless of whether there
+ // is an XMLDecl in this document
+ setScannerState(SCANNER_STATE_PROLOG);
+ setDispatcher(fPrologDispatcher);
+
+ // scan XMLDecl
+ try {
+ if (fEntityScanner.skipString("')) {
+ reportFatalError("DoctypedeclUnterminated", new Object[]{fDoctypeName});
+ }
+ fMarkupDepth--;
+
+ // scan external subset next
+ if (fDoctypeSystemId != null) {
+ fIsEntityDeclaredVC = !fStandalone;
+ if (readExternalSubset) {
+ setScannerState(SCANNER_STATE_DTD_EXTERNAL);
+ break;
+ }
+ }
+ else if (fExternalSubsetSource != null) {
+ fIsEntityDeclaredVC = !fStandalone;
+ if (readExternalSubset) {
+ // This handles the case of a DOCTYPE that only had an internal subset.
+ fDTDScanner.setInputSource(fExternalSubsetSource);
+ fExternalSubsetSource = null;
+ setScannerState(SCANNER_STATE_DTD_EXTERNAL_DECLS);
+ break;
+ }
+ }
+ // This document only has an internal subset. If it contains parameter entity
+ // references and standalone="no" then [Entity Declared] is a validity constraint.
+ else {
+ fIsEntityDeclaredVC = fEntityManager.hasPEReferences() && !fStandalone;
+ }
+
+ // break out of this dispatcher.
+ setScannerState(SCANNER_STATE_PROLOG);
+ setDispatcher(fPrologDispatcher);
+ fEntityManager.setEntityHandler(XMLDocumentScannerImpl.this);
+ return true;
+ }
+ break;
+ }
+ case SCANNER_STATE_DTD_EXTERNAL: {
+ fDTDDescription.setValues(fDoctypePublicId, fDoctypeSystemId, null, null);
+ fDTDDescription.setRootName(fDoctypeName);
+ XMLInputSource xmlInputSource =
+ fEntityManager.resolveEntity(fDTDDescription);
+ fDTDScanner.setInputSource(xmlInputSource);
+ setScannerState(SCANNER_STATE_DTD_EXTERNAL_DECLS);
+ again = true;
+ break;
+ }
+ case SCANNER_STATE_DTD_EXTERNAL_DECLS: {
+ // REVISIT: Should there be a feature for
+ // the "complete" parameter?
+ boolean completeDTD = true;
+ boolean moreToScan = fDTDScanner.scanDTDExternalSubset(completeDTD);
+ if (!moreToScan) {
+ setScannerState(SCANNER_STATE_PROLOG);
+ setDispatcher(fPrologDispatcher);
+ fEntityManager.setEntityHandler(XMLDocumentScannerImpl.this);
+ return true;
+ }
+ break;
+ }
+ default: {
+ throw new XNIException("DTDDispatcher#dispatch: scanner state="+fScannerState+" ("+getScannerStateName(fScannerState)+')');
+ }
+ }
+ } while (complete || again);
+ }
+ // encoding errors
+ catch (MalformedByteSequenceException e) {
+ fErrorReporter.reportError(e.getDomain(), e.getKey(),
+ e.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+ return false;
+ }
+ catch (CharConversionException e) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XML_DOMAIN,
+ "CharConversionFailure",
+ null,
+ XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+ return false;
+ }
+ // premature end of file
+ catch (EOFException e) {
+ reportFatalError("PrematureEOF", null);
+ return false;
+ //throw e;
+ }
+
+ // cleanup
+ finally {
+ fEntityManager.setEntityHandler(XMLDocumentScannerImpl.this);
+ }
+
+ return true;
+
+ } // dispatch(boolean):boolean
+
+ } // class DTDDispatcher
+
+ /**
+ * Dispatcher to handle content scanning.
+ *
+ * @author Andy Clark, IBM
+ * @author Eric Ye, IBM
+ */
+ protected class ContentDispatcher
+ extends FragmentContentDispatcher {
+
+ //
+ // Protected methods
+ //
+
+ // hooks
+
+ // NOTE: These hook methods are added so that the full document
+ // scanner can share the majority of code with this class.
+
+ /**
+ * Scan for DOCTYPE hook. This method is a hook for subclasses
+ * to add code to handle scanning for a the "DOCTYPE" string
+ * after the string "Attempt to locate an external subset for a document that does not otherwise
+ * have one. If an external subset is located, then it is scanned.
+ */
+ protected void resolveExternalSubsetAndRead()
+ throws IOException, XNIException {
+
+ fDTDDescription.setValues(null, null, fEntityManager.getCurrentResourceIdentifier().getExpandedSystemId(), null);
+ fDTDDescription.setRootName(fElementQName.rawname);
+ XMLInputSource src = fExternalSubsetResolver.getExternalSubset(fDTDDescription);
+
+ if (src != null) {
+ fDoctypeName = fElementQName.rawname;
+ fDoctypePublicId = src.getPublicId();
+ fDoctypeSystemId = src.getSystemId();
+ // call document handler
+ if (fDocumentHandler != null) {
+ // This inserts a doctypeDecl event into the stream though no
+ // DOCTYPE existed in the instance document.
+ fDocumentHandler.doctypeDecl(fDoctypeName, fDoctypePublicId, fDoctypeSystemId, null);
+ }
+ try {
+ if (fValidationManager == null || !fValidationManager.isCachedDTD()) {
+ fDTDScanner.setInputSource(src);
+ while (fDTDScanner.scanDTDExternalSubset(true));
+ }
+ else {
+ // This sends startDTD and endDTD calls down the pipeline.
+ fDTDScanner.setInputSource(null);
+ }
+ }
+ finally {
+ fEntityManager.setEntityHandler(XMLDocumentScannerImpl.this);
+ }
+ }
+ } // resolveExternalSubsetAndRead()
+
+ } // class ContentDispatcher
+
+ /**
+ * Dispatcher to handle trailing miscellaneous section scanning.
+ *
+ * @author Andy Clark, IBM
+ * @author Eric Ye, IBM
+ */
+ protected final class TrailingMiscDispatcher
+ implements Dispatcher {
+
+ //
+ // Dispatcher methods
+ //
+
+ /**
+ * Dispatch an XML "event".
+ *
+ * @param complete True if this dispatcher is intended to scan
+ * and dispatch as much as possible.
+ *
+ * @return True if there is more to dispatch either from this
+ * or a another dispatcher.
+ *
+ * @throws IOException Thrown on i/o error.
+ * @throws XNIException Thrown on parse error.
+ */
+ public boolean dispatch(boolean complete)
+ throws IOException, XNIException {
+
+ try {
+ boolean again;
+ do {
+ again = false;
+ switch (fScannerState) {
+ case SCANNER_STATE_TRAILING_MISC: {
+ fEntityScanner.skipSpaces();
+ if (fEntityScanner.skipChar('<')) {
+ setScannerState(SCANNER_STATE_START_OF_MARKUP);
+ again = true;
+ }
+ else {
+ setScannerState(SCANNER_STATE_CONTENT);
+ again = true;
+ }
+ break;
+ }
+ case SCANNER_STATE_START_OF_MARKUP: {
+ fMarkupDepth++;
+ if (fEntityScanner.skipChar('?')) {
+ setScannerState(SCANNER_STATE_PI);
+ again = true;
+ }
+ else if (fEntityScanner.skipChar('!')) {
+ setScannerState(SCANNER_STATE_COMMENT);
+ again = true;
+ }
+ else if (fEntityScanner.skipChar('/')) {
+ reportFatalError("MarkupNotRecognizedInMisc",
+ null);
+ again = true;
+ }
+ else if (isValidNameStartChar(fEntityScanner.peekChar())) {
+ reportFatalError("MarkupNotRecognizedInMisc",
+ null);
+ scanStartElement();
+ setScannerState(SCANNER_STATE_CONTENT);
+ }
+ else if (isValidNameStartHighSurrogate(fEntityScanner.peekChar())) {
+ reportFatalError("MarkupNotRecognizedInMisc",
+ null);
+ scanStartElement();
+ setScannerState(SCANNER_STATE_CONTENT);
+ }
+ else {
+ reportFatalError("MarkupNotRecognizedInMisc",
+ null);
+ }
+ break;
+ }
+ case SCANNER_STATE_PI: {
+ scanPI();
+ setScannerState(SCANNER_STATE_TRAILING_MISC);
+ break;
+ }
+ case SCANNER_STATE_COMMENT: {
+ if (!fEntityScanner.skipString("--")) {
+ reportFatalError("InvalidCommentStart", null);
+ }
+ scanComment();
+ setScannerState(SCANNER_STATE_TRAILING_MISC);
+ break;
+ }
+ case SCANNER_STATE_CONTENT: {
+ int ch = fEntityScanner.peekChar();
+ if (ch == -1) {
+ setScannerState(SCANNER_STATE_TERMINATED);
+ return false;
+ }
+ reportFatalError("ContentIllegalInTrailingMisc",
+ null);
+ fEntityScanner.scanChar();
+ setScannerState(SCANNER_STATE_TRAILING_MISC);
+ break;
+ }
+ case SCANNER_STATE_REFERENCE: {
+ reportFatalError("ReferenceIllegalInTrailingMisc",
+ null);
+ setScannerState(SCANNER_STATE_TRAILING_MISC);
+ break;
+ }
+ case SCANNER_STATE_TERMINATED: {
+ return false;
+ }
+ }
+ } while (complete || again);
+ }
+ // encoding errors
+ catch (MalformedByteSequenceException e) {
+ fErrorReporter.reportError(e.getDomain(), e.getKey(),
+ e.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+ return false;
+ }
+ catch (CharConversionException e) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XML_DOMAIN,
+ "CharConversionFailure",
+ null,
+ XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
+ return false;
+ }
+ catch (EOFException e) {
+ // NOTE: This is the only place we're allowed to reach
+ // the real end of the document stream. Unless the
+ // end of file was reached prematurely.
+ if (fMarkupDepth != 0) {
+ reportFatalError("PrematureEOF", null);
+ return false;
+ //throw e;
+ }
+
+ setScannerState(SCANNER_STATE_TERMINATED);
+ return false;
+ }
+
+ return true;
+
+ } // dispatch(boolean):boolean
+
+ } // class TrailingMiscDispatcher
+
+} // class XMLDocumentScannerImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XMLEntityDescription.java b/resources/xerces2-j-src/org/apache/xerces/impl/XMLEntityDescription.java
new file mode 100644
index 0000000..71135ae
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XMLEntityDescription.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import org.apache.xerces.xni.XMLResourceIdentifier;
+
+/**
+ * This interface describes the properties of entities--their
+ * physical location and their name.
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ *
+ * @version $Id$
+ */
+public interface XMLEntityDescription extends XMLResourceIdentifier {
+
+ /**
+ * Sets the name of the entity.
+ *
+ * @param name the name of the entity
+ */
+ public void setEntityName(String name);
+
+ /**
+ * Returns the name of the entity.
+ *
+ * @return the name of the entity
+ */
+ public String getEntityName();
+
+} // XMLEntityDescription
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XMLEntityHandler.java b/resources/xerces2-j-src/org/apache/xerces/impl/XMLEntityHandler.java
new file mode 100644
index 0000000..ce44da6
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XMLEntityHandler.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XNIException;
+
+/**
+ * The entity handler interface defines methods to report information
+ * about the start and end of entities.
+ *
+ * @xerces.internal
+ *
+ * @see org.apache.xerces.impl.XMLEntityScanner
+ *
+ * @author Andy Clark, IBM
+ *
+ * @version $Id$
+ */
+public interface XMLEntityHandler {
+
+ //
+ // XMLEntityHandler methods
+ //
+
+ /**
+ * This method notifies of the start of an entity. The DTD has the
+ * pseudo-name of "[dtd]" parameter entity names start with '%'; and
+ * general entities are just specified by their name.
+ *
+ * @param name The name of the entity.
+ * @param identifier The resource identifier.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal entities or a document entity that is
+ * parsed from a java.io.Reader).
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startEntity(String name,
+ XMLResourceIdentifier identifier,
+ String encoding, Augmentations augs) throws XNIException;
+
+ /**
+ * This method notifies the end of an entity. The DTD has the pseudo-name
+ * of "[dtd]" parameter entity names start with '%'; and general entities
+ * are just specified by their name.
+ *
+ * @param name The name of the entity.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endEntity(String name, Augmentations augs) throws XNIException;
+
+} // interface XMLEntityHandler
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XMLEntityManager.java b/resources/xerces2-j-src/org/apache/xerces/impl/XMLEntityManager.java
new file mode 100644
index 0000000..a2ff2ee
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XMLEntityManager.java
@@ -0,0 +1,3296 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Stack;
+import java.util.StringTokenizer;
+
+import org.apache.xerces.impl.io.ASCIIReader;
+import org.apache.xerces.impl.io.Latin1Reader;
+import org.apache.xerces.impl.io.UCSReader;
+import org.apache.xerces.impl.io.UTF16Reader;
+import org.apache.xerces.impl.io.UTF8Reader;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.impl.validation.ValidationManager;
+import org.apache.xerces.util.AugmentationsImpl;
+import org.apache.xerces.util.EncodingMap;
+import org.apache.xerces.util.HTTPInputSource;
+import org.apache.xerces.util.SecurityManager;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.URI;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.util.XMLEntityDescriptionImpl;
+import org.apache.xerces.util.XMLResourceIdentifierImpl;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLComponent;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+import org.apache.xerces.xni.parser.XMLInputSource;
+
+/**
+ * The entity manager handles the registration of general and parameter
+ * entities; resolves entities; and starts entities. The entity manager
+ * is a central component in a standard parser configuration and this
+ * class works directly with the entity scanner to manage the underlying
+ * xni.
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/validation
+ * - http://xml.org/sax/features/external-general-entities
+ * - http://xml.org/sax/features/external-parameter-entities
+ * - http://apache.org/xml/features/allow-java-encodings
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/entity-resolver
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ * @author Arnaud Le Hors, IBM
+ *
+ * @version $Id$
+ */
+public class XMLEntityManager
+ implements XMLComponent, XMLEntityResolver {
+
+ //
+ // Constants
+ //
+
+ /** Default buffer size (2048). */
+ public static final int DEFAULT_BUFFER_SIZE = 2048;
+
+ /** Default buffer size before we've finished with the XMLDecl: */
+ public static final int DEFAULT_XMLDECL_BUFFER_SIZE = 64;
+
+ /** Default internal entity buffer size (512). */
+ public static final int DEFAULT_INTERNAL_BUFFER_SIZE = 512;
+
+ // feature identifiers
+
+ /** Feature identifier: validation. */
+ protected static final String VALIDATION =
+ Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
+
+ /** Feature identifier: external general entities. */
+ protected static final String EXTERNAL_GENERAL_ENTITIES =
+ Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE;
+
+ /** Feature identifier: external parameter entities. */
+ protected static final String EXTERNAL_PARAMETER_ENTITIES =
+ Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE;
+
+ /** Feature identifier: allow Java encodings. */
+ protected static final String ALLOW_JAVA_ENCODINGS =
+ Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
+
+ /** Feature identifier: warn on duplicate EntityDef */
+ protected static final String WARN_ON_DUPLICATE_ENTITYDEF =
+ Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ENTITYDEF_FEATURE;
+
+ /** Feature identifier: standard uri conformant */
+ protected static final String STANDARD_URI_CONFORMANT =
+ Constants.XERCES_FEATURE_PREFIX +Constants.STANDARD_URI_CONFORMANT_FEATURE;
+
+ protected static final String PARSER_SETTINGS =
+ Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
+
+ // property identifiers
+
+ /** Property identifier: symbol table. */
+ protected static final String SYMBOL_TABLE =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
+
+ /** Property identifier: error reporter. */
+ protected static final String ERROR_REPORTER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
+
+ /** Property identifier: entity resolver. */
+ protected static final String ENTITY_RESOLVER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
+
+ // property identifier: ValidationManager
+ protected static final String VALIDATION_MANAGER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
+
+ /** property identifier: buffer size. */
+ protected static final String BUFFER_SIZE =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.BUFFER_SIZE_PROPERTY;
+
+ /** property identifier: security manager. */
+ protected static final String SECURITY_MANAGER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
+
+ // recognized features and properties
+
+ /** Recognized features. */
+ private static final String[] RECOGNIZED_FEATURES = {
+ VALIDATION,
+ EXTERNAL_GENERAL_ENTITIES,
+ EXTERNAL_PARAMETER_ENTITIES,
+ ALLOW_JAVA_ENCODINGS,
+ WARN_ON_DUPLICATE_ENTITYDEF,
+ STANDARD_URI_CONFORMANT
+ };
+
+ /** Feature defaults. */
+ private static final Boolean[] FEATURE_DEFAULTS = {
+ null,
+ Boolean.TRUE,
+ Boolean.TRUE,
+ Boolean.FALSE,
+ Boolean.FALSE,
+ Boolean.FALSE
+ };
+
+ /** Recognized properties. */
+ private static final String[] RECOGNIZED_PROPERTIES = {
+ SYMBOL_TABLE,
+ ERROR_REPORTER,
+ ENTITY_RESOLVER,
+ VALIDATION_MANAGER,
+ BUFFER_SIZE,
+ SECURITY_MANAGER,
+ };
+
+ /** Property defaults. */
+ private static final Object[] PROPERTY_DEFAULTS = {
+ null,
+ null,
+ null,
+ null,
+ new Integer(DEFAULT_BUFFER_SIZE),
+ null,
+ };
+
+ private static final String XMLEntity = "[xml]".intern();
+ private static final String DTDEntity = "[dtd]".intern();
+
+ // debugging
+
+ /**
+ * Debug printing of buffer. This debugging flag works best when you
+ * resize the DEFAULT_BUFFER_SIZE down to something reasonable like
+ * 64 characters.
+ */
+ private static final boolean DEBUG_BUFFER = false;
+
+ /** Debug some basic entities. */
+ private static final boolean DEBUG_ENTITIES = false;
+
+ /** Debug switching readers for encodings. */
+ private static final boolean DEBUG_ENCODINGS = false;
+
+ // should be diplayed trace resolving messages
+ private static final boolean DEBUG_RESOLVER = false;
+
+ //
+ // Data
+ //
+
+ // features
+
+ /**
+ * Validation. This feature identifier is:
+ * http://xml.org/sax/features/validation
+ */
+ protected boolean fValidation;
+
+ /**
+ * External general entities. This feature identifier is:
+ * http://xml.org/sax/features/external-general-entities
+ */
+ protected boolean fExternalGeneralEntities = true;
+
+ /**
+ * External parameter entities. This feature identifier is:
+ * http://xml.org/sax/features/external-parameter-entities
+ */
+ protected boolean fExternalParameterEntities = true;
+
+ /**
+ * Allow Java encoding names. This feature identifier is:
+ * http://apache.org/xml/features/allow-java-encodings
+ */
+ protected boolean fAllowJavaEncodings;
+
+ /** warn on duplicate Entity declaration.
+ * http://apache.org/xml/features/warn-on-duplicate-entitydef
+ */
+ protected boolean fWarnDuplicateEntityDef;
+
+ /**
+ * standard uri conformant (strict uri).
+ * http://apache.org/xml/features/standard-uri-conformant
+ */
+ protected boolean fStrictURI;
+
+ // properties
+
+ /**
+ * Symbol table. This property identifier is:
+ * http://apache.org/xml/properties/internal/symbol-table
+ */
+ protected SymbolTable fSymbolTable;
+
+ /**
+ * Error reporter. This property identifier is:
+ * http://apache.org/xml/properties/internal/error-reporter
+ */
+ protected XMLErrorReporter fErrorReporter;
+
+ /**
+ * Entity resolver. This property identifier is:
+ * http://apache.org/xml/properties/internal/entity-resolver
+ */
+ protected XMLEntityResolver fEntityResolver;
+
+ /**
+ * Validation manager. This property identifier is:
+ * http://apache.org/xml/properties/internal/validation-manager
+ */
+ protected ValidationManager fValidationManager;
+
+ // settings
+
+ /**
+ * Buffer size. We get this value from a property. The default size
+ * is used if the input buffer size property is not specified.
+ * REVISIT: do we need a property for internal entity buffer size?
+ */
+ protected int fBufferSize = DEFAULT_BUFFER_SIZE;
+
+ // stores defaults for entity expansion limit if it has
+ // been set on the configuration.
+ protected SecurityManager fSecurityManager = null;
+
+ /**
+ * True if the document entity is standalone. This should really
+ * only be set by the document source (e.g. XMLDocumentScanner).
+ */
+ protected boolean fStandalone;
+
+ /**
+ * True if the current document contains parameter entity references.
+ */
+ protected boolean fHasPEReferences;
+
+ // are the entities being parsed in the external subset?
+ // NOTE: this *is not* the same as whether they're external entities!
+ protected boolean fInExternalSubset = false;
+
+ // handlers
+
+ /** Entity handler. */
+ protected XMLEntityHandler fEntityHandler;
+
+ // scanner
+
+ /** Current entity scanner. */
+ protected XMLEntityScanner fEntityScanner;
+
+ /** XML 1.0 entity scanner. */
+ protected XMLEntityScanner fXML10EntityScanner;
+
+ /** XML 1.1 entity scanner. */
+ protected XMLEntityScanner fXML11EntityScanner;
+
+ // entity expansion limit (contains useful data if and only if
+ // fSecurityManager is non-null)
+ protected int fEntityExpansionLimit = 0;
+ // entity currently being expanded:
+ protected int fEntityExpansionCount = 0;
+
+ // entities
+
+ /** Entities. */
+ protected final Hashtable fEntities = new Hashtable();
+
+ /** Entity stack. */
+ protected final Stack fEntityStack = new Stack();
+
+ /** Current entity. */
+ protected ScannedEntity fCurrentEntity;
+
+ // shared context
+
+ /** Shared declared entities. */
+ protected Hashtable fDeclaredEntities;
+
+ // temp vars
+
+ /** Resource identifier. */
+ private final XMLResourceIdentifierImpl fResourceIdentifier = new XMLResourceIdentifierImpl();
+
+ /** Augmentations for entities. */
+ private final Augmentations fEntityAugs = new AugmentationsImpl();
+
+ /** Pool of byte buffers for single byte and variable width encodings, such as US-ASCII and UTF-8. */
+ private final ByteBufferPool fSmallByteBufferPool = new ByteBufferPool(fBufferSize);
+
+ /** Pool of byte buffers for 2-byte encodings, such as UTF-16. **/
+ private final ByteBufferPool fLargeByteBufferPool = new ByteBufferPool(fBufferSize << 1);
+
+ /** Temporary storage for the current entity's byte buffer. */
+ private byte[] fTempByteBuffer = null;
+
+ /** Pool of character buffers. */
+ private final CharacterBufferPool fCharacterBufferPool = new CharacterBufferPool(fBufferSize, DEFAULT_INTERNAL_BUFFER_SIZE);
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XMLEntityManager() {
+ this(null);
+ } // ()
+
+ /**
+ * Constructs an entity manager that shares the specified entity
+ * declarations during each parse.
+ *
+ * REVISIT: We might want to think about the "right"
+ * way to expose the list of declared entities. For now, the knowledge
+ * how to access the entity declarations is implicit.
+ */
+ public XMLEntityManager(XMLEntityManager entityManager) {
+
+ // save shared entity declarations
+ fDeclaredEntities = entityManager != null
+ ? entityManager.getDeclaredEntities() : null;
+
+ setScannerVersion(Constants.XML_VERSION_1_0);
+ } // (XMLEntityManager)
+
+ //
+ // Public methods
+ //
+
+ /**
+ * Sets whether the document entity is standalone.
+ *
+ * @param standalone True if document entity is standalone.
+ */
+ public void setStandalone(boolean standalone) {
+ fStandalone = standalone;
+ } // setStandalone(boolean)
+
+ /** Returns true if the document entity is standalone. */
+ public boolean isStandalone() {
+ return fStandalone;
+ } // isStandalone():boolean
+
+ /**
+ * Notifies the entity manager that the current document
+ * being processed contains parameter entity references.
+ */
+ final void notifyHasPEReferences() {
+ fHasPEReferences = true;
+ } // notifyHasPEReferences
+
+ /**
+ * Returns true if the document contains parameter entity references.
+ */
+ final boolean hasPEReferences() {
+ return fHasPEReferences;
+ } // hasPEReferences():boolean
+
+ /**
+ * Sets the entity handler. When an entity starts and ends, the
+ * entity handler is notified of the change.
+ *
+ * @param entityHandler The new entity handler.
+ */
+ public void setEntityHandler(XMLEntityHandler entityHandler) {
+ fEntityHandler = entityHandler;
+ } // setEntityHandler(XMLEntityHandler)
+
+ // this simply returns the fResourceIdentifier object;
+ // this should only be used with caution by callers that
+ // carefully manage the entity manager's behaviour, so that
+ // this doesn't returning meaningless or misleading data.
+ // @return a reference to the current fResourceIdentifier object
+ public XMLResourceIdentifier getCurrentResourceIdentifier() {
+ return fResourceIdentifier;
+ }
+
+ // this simply returns the fCurrentEntity object;
+ // this should only be used with caution by callers that
+ // carefully manage the entity manager's behaviour, so that
+ // this doesn't returning meaningless or misleading data.
+ // @return a reference to the current fCurrentEntity object
+ public ScannedEntity getCurrentEntity() {
+ return fCurrentEntity;
+ }
+
+ /**
+ * Adds an internal entity declaration.
+ *
+ * Note: This method ignores subsequent entity
+ * declarations.
+ *
+ * Note: The name should be a unique symbol. The
+ * SymbolTable can be used for this purpose.
+ *
+ * @param name The name of the entity.
+ * @param text The text of the entity.
+ * @param paramEntityRefs Count of direct and indirect references to parameter entities in the value of the entity.
+ *
+ * @see SymbolTable
+ */
+ public void addInternalEntity(String name, String text, int paramEntityRefs) {
+ if (!fEntities.containsKey(name)) {
+ Entity entity = new InternalEntity(name, text, fInExternalSubset, paramEntityRefs);
+ fEntities.put(name, entity);
+ }
+ else{
+ if(fWarnDuplicateEntityDef){
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_DUPLICATE_ENTITY_DEFINITION",
+ new Object[]{ name },
+ XMLErrorReporter.SEVERITY_WARNING );
+ }
+ }
+
+ } // addInternalEntity(String,String,int)
+
+ /**
+ * Adds an internal entity declaration.
+ *
+ * Note: This method ignores subsequent entity
+ * declarations.
+ *
+ * Note: The name should be a unique symbol. The
+ * SymbolTable can be used for this purpose.
+ *
+ * @param name The name of the entity.
+ * @param text The text of the entity.
+ *
+ * @see SymbolTable
+ */
+ public void addInternalEntity(String name, String text) {
+ addInternalEntity(name, text, 0);
+ } // addInternalEntity(String,String)
+
+ /**
+ * Returns the number of direct and indirect references to parameter
+ * entities in the value of the entity. This value will only be
+ * non-zero for an internal parameter entity.
+ *
+ * @param entityName The name of the entity to check.
+ * @return Count of direct and indirect references to parameter entities in the value of the entity
+ */
+ public int getParamEntityRefCount(String entityName) {
+ if (entityName != null &&
+ entityName.length() > 0 &&
+ entityName.charAt(0) == '%') {
+ final Entity entity = (Entity) fEntities.get(entityName);
+ if (entity != null && !entity.isExternal()) {
+ return ((InternalEntity) entity).paramEntityRefs;
+ }
+ }
+ return 0;
+ } // getParamEntityRefCount(String)
+
+ /**
+ * Adds an external entity declaration.
+ *
+ * Note: This method ignores subsequent entity
+ * declarations.
+ *
+ * Note: The name should be a unique symbol. The
+ * SymbolTable can be used for this purpose.
+ *
+ * @param name The name of the entity.
+ * @param publicId The public identifier of the entity.
+ * @param literalSystemId The system identifier of the entity.
+ * @param baseSystemId The base system identifier of the entity.
+ * This is the system identifier of the entity
+ * where the entity being added and
+ * is used to expand the system identifier when
+ * the system identifier is a relative URI.
+ * When null the system identifier of the first
+ * external entity on the stack is used instead.
+ *
+ * @see SymbolTable
+ */
+ public void addExternalEntity(String name,
+ String publicId, String literalSystemId,
+ String baseSystemId) throws IOException {
+ if (!fEntities.containsKey(name)) {
+ if (baseSystemId == null) {
+ // search for the first external entity on the stack
+ int size = fEntityStack.size();
+ if (size == 0 && fCurrentEntity != null && fCurrentEntity.entityLocation != null) {
+ baseSystemId = fCurrentEntity.entityLocation.getExpandedSystemId();
+ }
+ for (int i = size - 1; i >= 0 ; i--) {
+ ScannedEntity externalEntity =
+ (ScannedEntity)fEntityStack.elementAt(i);
+ if (externalEntity.entityLocation != null && externalEntity.entityLocation.getExpandedSystemId() != null) {
+ baseSystemId = externalEntity.entityLocation.getExpandedSystemId();
+ break;
+ }
+ }
+ }
+ Entity entity = new ExternalEntity(name,
+ new XMLEntityDescriptionImpl(name, publicId, literalSystemId, baseSystemId,
+ expandSystemId(literalSystemId, baseSystemId, false)), null, fInExternalSubset);
+ fEntities.put(name, entity);
+ }
+ else{
+ if(fWarnDuplicateEntityDef){
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_DUPLICATE_ENTITY_DEFINITION",
+ new Object[]{ name },
+ XMLErrorReporter.SEVERITY_WARNING );
+ }
+ }
+
+ } // addExternalEntity(String,String,String,String)
+
+ /**
+ * Checks whether an entity given by name is external.
+ *
+ * @param entityName The name of the entity to check.
+ * @return True if the entity is external, false otherwise
+ * (including when the entity is not declared).
+ */
+ public boolean isExternalEntity(String entityName) {
+
+ Entity entity = (Entity)fEntities.get(entityName);
+ if (entity == null) {
+ return false;
+ }
+ return entity.isExternal();
+ }
+
+ /**
+ * Checks whether the declaration of an entity given by name is
+ // in the external subset.
+ *
+ * @param entityName The name of the entity to check.
+ * @return True if the entity was declared in the external subset, false otherwise
+ * (including when the entity is not declared).
+ */
+ public boolean isEntityDeclInExternalSubset(String entityName) {
+
+ Entity entity = (Entity)fEntities.get(entityName);
+ if (entity == null) {
+ return false;
+ }
+ return entity.isEntityDeclInExternalSubset();
+ }
+
+ /**
+ * Adds an unparsed entity declaration.
+ *
+ * Note: This method ignores subsequent entity
+ * declarations.
+ *
+ * Note: The name should be a unique symbol. The
+ * SymbolTable can be used for this purpose.
+ *
+ * @param name The name of the entity.
+ * @param publicId The public identifier of the entity.
+ * @param systemId The system identifier of the entity.
+ * @param notation The name of the notation.
+ *
+ * @see SymbolTable
+ */
+ public void addUnparsedEntity(String name,
+ String publicId, String systemId,
+ String baseSystemId, String notation) {
+ if (!fEntities.containsKey(name)) {
+ Entity entity = new ExternalEntity(name,
+ new XMLEntityDescriptionImpl(name, publicId, systemId, baseSystemId, null),
+ notation, fInExternalSubset);
+ fEntities.put(name, entity);
+ }
+ else{
+ if(fWarnDuplicateEntityDef){
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_DUPLICATE_ENTITY_DEFINITION",
+ new Object[]{ name },
+ XMLErrorReporter.SEVERITY_WARNING );
+ }
+ }
+ } // addUnparsedEntity(String,String,String,String)
+
+ /**
+ * Checks whether an entity given by name is unparsed.
+ *
+ * @param entityName The name of the entity to check.
+ * @return True if the entity is unparsed, false otherwise
+ * (including when the entity is not declared).
+ */
+ public boolean isUnparsedEntity(String entityName) {
+
+ Entity entity = (Entity)fEntities.get(entityName);
+ if (entity == null) {
+ return false;
+ }
+ return entity.isUnparsed();
+ }
+
+ /**
+ * Checks whether an entity given by name is declared.
+ *
+ * @param entityName The name of the entity to check.
+ * @return True if the entity is declared, false otherwise.
+ */
+ public boolean isDeclaredEntity(String entityName) {
+
+ Entity entity = (Entity)fEntities.get(entityName);
+ return entity != null;
+ }
+
+ /**
+ * Resolves the specified public and system identifiers. This
+ * method first attempts to resolve the entity based on the
+ * EntityResolver registered by the application. If no entity
+ * resolver is registered or if the registered entity handler
+ * is unable to resolve the entity, then default entity
+ * resolution will occur.
+ *
+ * @param resourceIdentifier The XMLResourceIdentifier for the resource to resolve.
+ *
+ * @return Returns an input source that wraps the resolved entity.
+ * This method will never return null.
+ *
+ * @throws IOException Thrown on i/o error.
+ * @throws XNIException Thrown by entity resolver to signal an error.
+ */
+ public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier)
+ throws IOException, XNIException {
+ if(resourceIdentifier == null ) return null;
+ String publicId = resourceIdentifier.getPublicId();
+ String literalSystemId = resourceIdentifier.getLiteralSystemId();
+ String baseSystemId = resourceIdentifier.getBaseSystemId();
+ String expandedSystemId = resourceIdentifier.getExpandedSystemId();
+ // if no base systemId given, assume that it's relative
+ // to the systemId of the current scanned entity
+ // Sometimes the system id is not (properly) expanded.
+ // We need to expand the system id if:
+ // a. the expanded one was null; or
+ // b. the base system id was null, but becomes non-null from the current entity.
+ boolean needExpand = (expandedSystemId == null);
+ // REVISIT: why would the baseSystemId ever be null? if we
+ // didn't have to make this check we wouldn't have to reuse the
+ // fXMLResourceIdentifier object...
+ if (baseSystemId == null && fCurrentEntity != null && fCurrentEntity.entityLocation != null) {
+ baseSystemId = fCurrentEntity.entityLocation.getExpandedSystemId();
+ if (baseSystemId != null)
+ needExpand = true;
+ }
+
+ // give the entity resolver a chance
+ XMLInputSource xmlInputSource = null;
+ if (fEntityResolver != null) {
+ if (needExpand) {
+ expandedSystemId = expandSystemId(literalSystemId, baseSystemId, false);
+ }
+ resourceIdentifier.setBaseSystemId(baseSystemId);
+ resourceIdentifier.setExpandedSystemId(expandedSystemId);
+ xmlInputSource = fEntityResolver.resolveEntity(resourceIdentifier);
+ }
+
+ // do default resolution
+ // REVISIT: what's the correct behavior if the user provided an entity
+ // resolver (fEntityResolver != null), but resolveEntity doesn't return
+ // an input source (xmlInputSource == null)?
+ // do we do default resolution, or do we just return null? -SG
+ if (xmlInputSource == null) {
+ // REVISIT: when systemId is null, I think we should return null.
+ // is this the right solution? -SG
+ //if (systemId != null)
+ xmlInputSource = new XMLInputSource(publicId, literalSystemId, baseSystemId);
+ }
+
+ if (DEBUG_RESOLVER) {
+ System.err.println("XMLEntityManager.resolveEntity(" + publicId + ")");
+ System.err.println(" = " + xmlInputSource);
+ }
+
+ return xmlInputSource;
+
+ } // resolveEntity(XMLResourceIdentifier):XMLInputSource
+
+ /**
+ * Starts a named entity.
+ *
+ * @param entityName The name of the entity to start.
+ * @param literal True if this entity is started within a literal
+ * value.
+ *
+ * @throws IOException Thrown on i/o error.
+ * @throws XNIException Thrown by entity handler to signal an error.
+ */
+ public void startEntity(String entityName, boolean literal)
+ throws IOException, XNIException {
+
+ // was entity declared?
+ Entity entity = (Entity)fEntities.get(entityName);
+ if (entity == null) {
+ if (fEntityHandler != null) {
+ String encoding = null;
+ fResourceIdentifier.clear();
+ fEntityAugs.removeAllItems();
+ fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
+ fEntityHandler.startEntity(entityName, fResourceIdentifier, encoding, fEntityAugs);
+ fEntityAugs.removeAllItems();
+ fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
+ fEntityHandler.endEntity(entityName, fEntityAugs);
+ }
+ return;
+ }
+
+ // should we skip external entities?
+ boolean external = entity.isExternal();
+ if (external && (fValidationManager == null || !fValidationManager.isCachedDTD())) {
+ boolean unparsed = entity.isUnparsed();
+ boolean parameter = entityName.startsWith("%");
+ boolean general = !parameter;
+ if (unparsed || (general && !fExternalGeneralEntities) ||
+ (parameter && !fExternalParameterEntities)) {
+ if (fEntityHandler != null) {
+ fResourceIdentifier.clear();
+ final String encoding = null;
+ ExternalEntity externalEntity = (ExternalEntity)entity;
+ //REVISIT: since we're storing expandedSystemId in the
+ // externalEntity, how could this have got here if it wasn't already
+ // expanded??? - neilg
+ String extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null);
+ String extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null);
+ String expandedSystemId = expandSystemId(extLitSysId, extBaseSysId, false);
+ fResourceIdentifier.setValues(
+ (externalEntity.entityLocation != null ? externalEntity.entityLocation.getPublicId() : null),
+ extLitSysId, extBaseSysId, expandedSystemId);
+ fEntityAugs.removeAllItems();
+ fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
+ fEntityHandler.startEntity(entityName, fResourceIdentifier, encoding, fEntityAugs);
+ fEntityAugs.removeAllItems();
+ fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
+ fEntityHandler.endEntity(entityName, fEntityAugs);
+ }
+ return;
+ }
+ }
+
+ // is entity recursive?
+ int size = fEntityStack.size();
+ for (int i = size; i >= 0; i--) {
+ Entity activeEntity = i == size
+ ? fCurrentEntity
+ : (Entity)fEntityStack.elementAt(i);
+ if (activeEntity.name == entityName) {
+ StringBuffer path = new StringBuffer(entityName);
+ for (int j = i + 1; j < size; j++) {
+ activeEntity = (Entity)fEntityStack.elementAt(j);
+ path.append(" -> ");
+ path.append(activeEntity.name);
+ }
+ path.append(" -> ");
+ path.append(fCurrentEntity.name);
+ path.append(" -> ");
+ path.append(entityName);
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "RecursiveReference",
+ new Object[] { entityName, path.toString() },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ if (fEntityHandler != null) {
+ fResourceIdentifier.clear();
+ final String encoding = null;
+ if (external) {
+ ExternalEntity externalEntity = (ExternalEntity)entity;
+ // REVISIT: for the same reason above...
+ String extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null);
+ String extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null);
+ String expandedSystemId = expandSystemId(extLitSysId, extBaseSysId, false);
+ fResourceIdentifier.setValues(
+ (externalEntity.entityLocation != null ? externalEntity.entityLocation.getPublicId() : null),
+ extLitSysId, extBaseSysId, expandedSystemId);
+ }
+ fEntityAugs.removeAllItems();
+ fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
+ fEntityHandler.startEntity(entityName, fResourceIdentifier, encoding, fEntityAugs);
+ fEntityAugs.removeAllItems();
+ fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
+ fEntityHandler.endEntity(entityName, fEntityAugs);
+ }
+ return;
+ }
+ }
+
+ // resolve external entity
+ XMLInputSource xmlInputSource = null;
+ if (external) {
+ ExternalEntity externalEntity = (ExternalEntity)entity;
+ xmlInputSource = resolveEntity(externalEntity.entityLocation);
+ }
+
+ // wrap internal entity
+ else {
+ InternalEntity internalEntity = (InternalEntity)entity;
+ Reader reader = new StringReader(internalEntity.text);
+ xmlInputSource = new XMLInputSource(null, null, null, reader, null);
+ }
+
+ // start the entity
+ startEntity(entityName, xmlInputSource, literal, external);
+
+ } // startEntity(String,boolean)
+
+ /**
+ * Starts the document entity. The document entity has the "[xml]"
+ * pseudo-name.
+ *
+ * @param xmlInputSource The input source of the document entity.
+ *
+ * @throws IOException Thrown on i/o error.
+ * @throws XNIException Thrown by entity handler to signal an error.
+ */
+ public void startDocumentEntity(XMLInputSource xmlInputSource)
+ throws IOException, XNIException {
+ startEntity(XMLEntity, xmlInputSource, false, true);
+ } // startDocumentEntity(XMLInputSource)
+
+ /**
+ * Starts the DTD entity. The DTD entity has the "[dtd]"
+ * pseudo-name.
+ *
+ * @param xmlInputSource The input source of the DTD entity.
+ *
+ * @throws IOException Thrown on i/o error.
+ * @throws XNIException Thrown by entity handler to signal an error.
+ */
+ public void startDTDEntity(XMLInputSource xmlInputSource)
+ throws IOException, XNIException {
+ startEntity(DTDEntity, xmlInputSource, false, true);
+ } // startDTDEntity(XMLInputSource)
+
+ // indicate start of external subset so that
+ // location of entity decls can be tracked
+ public void startExternalSubset() {
+ fInExternalSubset = true;
+ }
+
+ public void endExternalSubset() {
+ fInExternalSubset = false;
+ }
+
+ /**
+ * Starts an entity.
+ *
+ * This method can be used to insert an application defined XML
+ * entity stream into the parsing stream.
+ *
+ * @param name The name of the entity.
+ * @param xmlInputSource The input source of the entity.
+ * @param literal True if this entity is started within a
+ * literal value.
+ * @param isExternal whether this entity should be treated as an internal or external entity.
+ *
+ * @throws IOException Thrown on i/o error.
+ * @throws XNIException Thrown by entity handler to signal an error.
+ */
+ public void startEntity(String name,
+ XMLInputSource xmlInputSource,
+ boolean literal, boolean isExternal)
+ throws IOException, XNIException {
+
+ String encoding = setupCurrentEntity(name, xmlInputSource, literal, isExternal);
+
+ // when entity expansion limit is set by the Application, we need to
+ // check for the entity expansion limit set by the parser, if number of entity
+ // expansions exceeds the entity expansion limit, parser will throw fatal error.
+ // Note that this is intentionally unbalanced; it counts
+ // the number of expansions *per document*.
+ if (fSecurityManager != null) {
+ fEntityExpansionCount += getParamEntityRefCount(name);
+ if (fEntityExpansionCount++ > fEntityExpansionLimit) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "EntityExpansionLimitExceeded",
+ new Object[]{new Integer(fEntityExpansionLimit) },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR );
+ // is there anything better to do than reset the counter?
+ // at least one can envision debugging applications where this might
+ // be useful...
+ fEntityExpansionCount = 0;
+ }
+ }
+
+ // call handler
+ if (fEntityHandler != null) {
+ fEntityHandler.startEntity(name, fResourceIdentifier, encoding, null);
+ }
+
+ } // startEntity(String,XMLInputSource)
+
+ /**
+ * This method uses the passed-in XMLInputSource to make
+ * fCurrentEntity usable for reading.
+ * @param name name of the entity (XML is it's the document entity)
+ * @param xmlInputSource the input source, with sufficient information
+ * to begin scanning characters.
+ * @param literal True if this entity is started within a
+ * literal value.
+ * @param isExternal whether this entity should be treated as an internal or external entity.
+ * @throws IOException if anything can't be read
+ * XNIException If any parser-specific goes wrong.
+ * @return the encoding of the new entity or null if a character stream was employed
+ */
+ public String setupCurrentEntity(String name, XMLInputSource xmlInputSource,
+ boolean literal, boolean isExternal)
+ throws IOException, XNIException {
+ // get information
+
+ final String publicId = xmlInputSource.getPublicId();
+ String literalSystemId = xmlInputSource.getSystemId();
+ String baseSystemId = xmlInputSource.getBaseSystemId();
+ String encoding = xmlInputSource.getEncoding();
+ final boolean encodingExternallySpecified = (encoding != null);
+ Boolean isBigEndian = null;
+ fTempByteBuffer = null;
+
+ // create reader
+ InputStream stream = null;
+ Reader reader = xmlInputSource.getCharacterStream();
+ // First chance checking strict URI
+ String expandedSystemId = expandSystemId(literalSystemId, baseSystemId, fStrictURI);
+ if (baseSystemId == null) {
+ baseSystemId = expandedSystemId;
+ }
+ if (reader == null) {
+ stream = xmlInputSource.getByteStream();
+ if (stream == null) {
+ URL location = new URL(expandedSystemId);
+ URLConnection connect = location.openConnection();
+ if (!(connect instanceof HttpURLConnection)) {
+ stream = connect.getInputStream();
+ }
+ else {
+ boolean followRedirects = true;
+
+ // setup URLConnection if we have an HTTPInputSource
+ if (xmlInputSource instanceof HTTPInputSource) {
+ final HttpURLConnection urlConnection = (HttpURLConnection) connect;
+ final HTTPInputSource httpInputSource = (HTTPInputSource) xmlInputSource;
+
+ // set request properties
+ Iterator propIter = httpInputSource.getHTTPRequestProperties();
+ while (propIter.hasNext()) {
+ Map.Entry entry = (Map.Entry) propIter.next();
+ urlConnection.setRequestProperty((String) entry.getKey(), (String) entry.getValue());
+ }
+
+ // set preference for redirection
+ followRedirects = httpInputSource.getFollowHTTPRedirects();
+ if (!followRedirects) {
+ urlConnection.setInstanceFollowRedirects(followRedirects);
+ }
+ }
+
+ stream = connect.getInputStream();
+
+ // REVISIT: If the URLConnection has external encoding
+ // information, we should be reading it here. It's located
+ // in the charset parameter of Content-Type. -- mrglavas
+
+ if (followRedirects) {
+ String redirect = connect.getURL().toString();
+ // E43: Check if the URL was redirected, and then
+ // update literal and expanded system IDs if needed.
+ if (!redirect.equals(expandedSystemId)) {
+ literalSystemId = redirect;
+ expandedSystemId = redirect;
+ }
+ }
+ }
+ }
+ // wrap this stream in RewindableInputStream
+ RewindableInputStream rewindableStream = new RewindableInputStream(stream);
+ stream = rewindableStream;
+
+ // perform auto-detect of encoding if necessary
+ if (encoding == null) {
+ // read first four bytes and determine encoding
+ final byte[] b4 = new byte[4];
+ int count = 0;
+ for (; count<4; count++ ) {
+ b4[count] = (byte)rewindableStream.readAndBuffer();
+ }
+ if (count == 4) {
+ final EncodingInfo info = getEncodingInfo(b4, count);
+ encoding = info.autoDetectedEncoding;
+ final String readerEncoding = info.readerEncoding;
+ isBigEndian = info.isBigEndian;
+ stream.reset();
+ if (info.hasBOM) {
+ // Special case UTF-8 files with BOM created by Microsoft
+ // tools. It's more efficient to consume the BOM than make
+ // the reader perform extra checks. -Ac
+ if (readerEncoding == "UTF-8") {
+ // UTF-8 BOM: 0xEF 0xBB 0xBF
+ stream.skip(3);
+ }
+ // It's also more efficient to consume the UTF-16 BOM.
+ else if (readerEncoding == "UTF-16") {
+ // UTF-16 BE BOM: 0xFE 0xFF
+ // UTF-16 LE BOM: 0xFF 0xFE
+ stream.skip(2);
+ }
+ }
+ reader = createReader(stream, readerEncoding, isBigEndian);
+ }
+ else {
+ reader = createReader(stream, encoding, isBigEndian);
+ }
+ }
+
+ // use specified encoding
+ else {
+ encoding = encoding.toUpperCase(Locale.ENGLISH);
+
+ // If encoding is UTF-8, consume BOM if one is present.
+ if (encoding.equals("UTF-8")) {
+ final int[] b3 = new int[3];
+ int count = 0;
+ for (; count < 3; ++count) {
+ b3[count] = rewindableStream.readAndBuffer();
+ if (b3[count] == -1)
+ break;
+ }
+ if (count == 3) {
+ if (b3[0] != 0xEF || b3[1] != 0xBB || b3[2] != 0xBF) {
+ // First three bytes are not BOM, so reset.
+ stream.reset();
+ }
+ }
+ else {
+ stream.reset();
+ }
+ reader = createReader(stream, "UTF-8", isBigEndian);
+ }
+ // If encoding is UTF-16, we still need to read the first
+ // four bytes, in order to discover the byte order.
+ else if (encoding.equals("UTF-16")) {
+ final int[] b4 = new int[4];
+ int count = 0;
+ for (; count < 4; ++count) {
+ b4[count] = rewindableStream.readAndBuffer();
+ if (b4[count] == -1)
+ break;
+ }
+ stream.reset();
+ if (count >= 2) {
+ final int b0 = b4[0];
+ final int b1 = b4[1];
+ if (b0 == 0xFE && b1 == 0xFF) {
+ // UTF-16, big-endian
+ isBigEndian = Boolean.TRUE;
+ stream.skip(2);
+ }
+ else if (b0 == 0xFF && b1 == 0xFE) {
+ // UTF-16, little-endian
+ isBigEndian = Boolean.FALSE;
+ stream.skip(2);
+ }
+ else if (count == 4) {
+ final int b2 = b4[2];
+ final int b3 = b4[3];
+ if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
+ // UTF-16, big-endian, no BOM
+ isBigEndian = Boolean.TRUE;
+ }
+ if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
+ // UTF-16, little-endian, no BOM
+ isBigEndian = Boolean.FALSE;
+ }
+ }
+ }
+ reader = createReader(stream, "UTF-16", isBigEndian);
+ }
+ // If encoding is UCS-4, we still need to read the first four bytes
+ // in order to discover the byte order.
+ else if (encoding.equals("ISO-10646-UCS-4")) {
+ final int[] b4 = new int[4];
+ int count = 0;
+ for (; count < 4; ++count) {
+ b4[count] = rewindableStream.readAndBuffer();
+ if (b4[count] == -1)
+ break;
+ }
+ stream.reset();
+
+ // Ignore unusual octet order for now.
+ if (count == 4) {
+ // UCS-4, big endian (1234)
+ if (b4[0] == 0x00 && b4[1] == 0x00 && b4[2] == 0x00 && b4[3] == 0x3C) {
+ isBigEndian = Boolean.TRUE;
+ }
+ // UCS-4, little endian (1234)
+ else if (b4[0] == 0x3C && b4[1] == 0x00 && b4[2] == 0x00 && b4[3] == 0x00) {
+ isBigEndian = Boolean.FALSE;
+ }
+ }
+ reader = createReader(stream, encoding, isBigEndian);
+ }
+ // If encoding is UCS-2, we still need to read the first four bytes
+ // in order to discover the byte order.
+ else if (encoding.equals("ISO-10646-UCS-2")) {
+ final int[] b4 = new int[4];
+ int count = 0;
+ for (; count < 4; ++count) {
+ b4[count] = rewindableStream.readAndBuffer();
+ if (b4[count] == -1)
+ break;
+ }
+ stream.reset();
+
+ if (count == 4) {
+ // UCS-2, big endian
+ if (b4[0] == 0x00 && b4[1] == 0x3C && b4[2] == 0x00 && b4[3] == 0x3F) {
+ isBigEndian = Boolean.TRUE;
+ }
+ // UCS-2, little endian
+ else if (b4[0] == 0x3C && b4[1] == 0x00 && b4[2] == 0x3F && b4[3] == 0x00) {
+ isBigEndian = Boolean.FALSE;
+ }
+ }
+ reader = createReader(stream, encoding, isBigEndian);
+ }
+ else {
+ reader = createReader(stream, encoding, isBigEndian);
+ }
+ }
+
+ // read one character at a time so we don't jump too far
+ // ahead, converting characters from the byte stream in
+ // the wrong encoding
+ if (DEBUG_ENCODINGS) {
+ System.out.println("$$$ no longer wrapping reader in OneCharReader");
+ }
+ //reader = new OneCharReader(reader);
+ }
+
+ // We've seen a new Reader.
+ // Push it on the stack so we can close it later.
+ fReaderStack.push(reader);
+
+ // push entity on stack
+ if (fCurrentEntity != null) {
+ fEntityStack.push(fCurrentEntity);
+ }
+
+ // create entity
+ fCurrentEntity = new ScannedEntity(name,
+ new XMLResourceIdentifierImpl(publicId, literalSystemId, baseSystemId, expandedSystemId),
+ stream, reader, fTempByteBuffer, encoding, literal, false, isExternal);
+ fCurrentEntity.setEncodingExternallySpecified(encodingExternallySpecified);
+ fEntityScanner.setCurrentEntity(fCurrentEntity);
+ fResourceIdentifier.setValues(publicId, literalSystemId, baseSystemId, expandedSystemId);
+ return encoding;
+ } //setupCurrentEntity(String, XMLInputSource, boolean, boolean): String
+
+ // set version of scanner to use
+ public void setScannerVersion(short version) {
+ if(version == Constants.XML_VERSION_1_0) {
+ if(fXML10EntityScanner == null) {
+ fXML10EntityScanner = new XMLEntityScanner();
+ }
+ fXML10EntityScanner.reset(fSymbolTable, this, fErrorReporter);
+ fEntityScanner = fXML10EntityScanner;
+ fEntityScanner.setCurrentEntity(fCurrentEntity);
+ } else {
+ if(fXML11EntityScanner == null) {
+ fXML11EntityScanner = new XML11EntityScanner();
+ }
+ fXML11EntityScanner.reset(fSymbolTable, this, fErrorReporter);
+ fEntityScanner = fXML11EntityScanner;
+ fEntityScanner.setCurrentEntity(fCurrentEntity);
+ }
+ } // setScannerVersion(short)
+
+ /** Returns the entity scanner. */
+ public XMLEntityScanner getEntityScanner() {
+ if(fEntityScanner == null) {
+ // default to 1.0
+ if(fXML10EntityScanner == null) {
+ fXML10EntityScanner = new XMLEntityScanner();
+ }
+ fXML10EntityScanner.reset(fSymbolTable, this, fErrorReporter);
+ fEntityScanner = fXML10EntityScanner;
+ }
+ return fEntityScanner;
+ } // getEntityScanner():XMLEntityScanner
+
+ // A stack containing all the open readers
+ protected Stack fReaderStack = new Stack();
+
+ /**
+ * Close all opened InputStreams and Readers opened by this parser.
+ */
+ public void closeReaders() {
+ // close all readers
+ for (int i = fReaderStack.size()-1; i >= 0; i--) {
+ try {
+ ((Reader)fReaderStack.pop()).close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+
+ //
+ // XMLComponent methods
+ //
+
+ /**
+ * Resets the component. The component can query the component manager
+ * about any features and properties that affect the operation of the
+ * component.
+ *
+ * @param componentManager The component manager.
+ *
+ * @throws SAXException Thrown by component on initialization error.
+ * For example, if a feature or property is
+ * required for the operation of the component, the
+ * component manager may throw a
+ * SAXNotRecognizedException or a
+ * SAXNotSupportedException.
+ */
+ public void reset(XMLComponentManager componentManager)
+ throws XMLConfigurationException {
+
+ boolean parser_settings;
+ try {
+ parser_settings = componentManager.getFeature(PARSER_SETTINGS);
+ } catch (XMLConfigurationException e) {
+ parser_settings = true;
+ }
+
+ if (!parser_settings) {
+ // parser settings have not been changed
+ reset();
+ return;
+ }
+
+ // sax features
+ try {
+ fValidation = componentManager.getFeature(VALIDATION);
+ }
+ catch (XMLConfigurationException e) {
+ fValidation = false;
+ }
+ try {
+ fExternalGeneralEntities = componentManager.getFeature(EXTERNAL_GENERAL_ENTITIES);
+ }
+ catch (XMLConfigurationException e) {
+ fExternalGeneralEntities = true;
+ }
+ try {
+ fExternalParameterEntities = componentManager.getFeature(EXTERNAL_PARAMETER_ENTITIES);
+ }
+ catch (XMLConfigurationException e) {
+ fExternalParameterEntities = true;
+ }
+
+ // xerces features
+ try {
+ fAllowJavaEncodings = componentManager.getFeature(ALLOW_JAVA_ENCODINGS);
+ }
+ catch (XMLConfigurationException e) {
+ fAllowJavaEncodings = false;
+ }
+
+ try {
+ fWarnDuplicateEntityDef = componentManager.getFeature(WARN_ON_DUPLICATE_ENTITYDEF);
+ }
+ catch (XMLConfigurationException e) {
+ fWarnDuplicateEntityDef = false;
+ }
+
+ try {
+ fStrictURI = componentManager.getFeature(STANDARD_URI_CONFORMANT);
+ }
+ catch (XMLConfigurationException e) {
+ fStrictURI = false;
+ }
+
+ // xerces properties
+ fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
+ fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
+ try {
+ fEntityResolver = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER);
+ }
+ catch (XMLConfigurationException e) {
+ fEntityResolver = null;
+ }
+ try {
+ fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
+ }
+ catch (XMLConfigurationException e) {
+ fValidationManager = null;
+ }
+ try {
+ fSecurityManager = (SecurityManager)componentManager.getProperty(SECURITY_MANAGER);
+ }
+ catch (XMLConfigurationException e) {
+ fSecurityManager = null;
+ }
+
+ // reset general state
+ reset();
+
+ } // reset(XMLComponentManager)
+
+ // reset general state. Should not be called other than by
+ // a class acting as a component manager but not
+ // implementing that interface for whatever reason.
+ public void reset() {
+ fEntityExpansionLimit = (fSecurityManager != null)?fSecurityManager.getEntityExpansionLimit():0;
+
+ // initialize state
+ fStandalone = false;
+ fHasPEReferences = false;
+ fEntities.clear();
+ fEntityStack.removeAllElements();
+ fEntityExpansionCount = 0;
+
+ fCurrentEntity = null;
+ // reset scanner
+ if(fXML10EntityScanner != null){
+ fXML10EntityScanner.reset(fSymbolTable, this, fErrorReporter);
+ }
+ if(fXML11EntityScanner != null) {
+ fXML11EntityScanner.reset(fSymbolTable, this, fErrorReporter);
+ }
+
+ // DEBUG
+ if (DEBUG_ENTITIES) {
+ addInternalEntity("text", "Hello, World.");
+ addInternalEntity("empty-element", "");
+ addInternalEntity("balanced-element", "");
+ addInternalEntity("balanced-element-with-text", "Hello, World");
+ addInternalEntity("balanced-element-with-entity", "&text;");
+ addInternalEntity("unbalanced-entity", "");
+ addInternalEntity("recursive-entity", "&recursive-entity2;");
+ addInternalEntity("recursive-entity2", "&recursive-entity3;");
+ addInternalEntity("recursive-entity3", "&recursive-entity;");
+ try {
+ addExternalEntity("external-text", null, "external-text.ent", "test/external-text.xml");
+ addExternalEntity("external-balanced-element", null, "external-balanced-element.ent", "test/external-balanced-element.xml");
+ addExternalEntity("one", null, "ent/one.ent", "test/external-entity.xml");
+ addExternalEntity("two", null, "ent/two.ent", "test/ent/one.xml");
+ }
+ catch (IOException ex) {
+ // should never happen
+ }
+ }
+
+ // copy declared entities
+ if (fDeclaredEntities != null) {
+ Iterator entries = fDeclaredEntities.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ Object key = entry.getKey();
+ Object value = entry.getValue();
+ fEntities.put(key, value);
+ }
+ }
+ fEntityHandler = null;
+
+ } // reset(XMLComponentManager)
+
+ /**
+ * Returns a list of feature identifiers that are recognized by
+ * this component. This method may return null if no features
+ * are recognized by this component.
+ */
+ public String[] getRecognizedFeatures() {
+ return (String[])(RECOGNIZED_FEATURES.clone());
+ } // getRecognizedFeatures():String[]
+
+ /**
+ * Sets the state of a feature. This method is called by the component
+ * manager any time after reset when a feature changes state.
+ *
+ * Note: Components should silently ignore features
+ * that do not affect the operation of the component.
+ *
+ * @param featureId The feature identifier.
+ * @param state The state of the feature.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setFeature(String featureId, boolean state)
+ throws XMLConfigurationException {
+
+ // xerces features
+ if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
+ final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
+ if (suffixLength == Constants.ALLOW_JAVA_ENCODINGS_FEATURE.length() &&
+ featureId.endsWith(Constants.ALLOW_JAVA_ENCODINGS_FEATURE)) {
+ fAllowJavaEncodings = state;
+ }
+ }
+
+ } // setFeature(String,boolean)
+
+ /**
+ * Returns a list of property identifiers that are recognized by
+ * this component. This method may return null if no properties
+ * are recognized by this component.
+ */
+ public String[] getRecognizedProperties() {
+ return (String[])(RECOGNIZED_PROPERTIES.clone());
+ } // getRecognizedProperties():String[]
+
+ /**
+ * Sets the value of a property. This method is called by the component
+ * manager any time after reset when a property changes value.
+ *
+ * Note: Components should silently ignore properties
+ * that do not affect the operation of the component.
+ *
+ * @param propertyId The property identifier.
+ * @param value The value of the property.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setProperty(String propertyId, Object value)
+ throws XMLConfigurationException {
+
+ // Xerces properties
+ if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
+ final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
+
+ if (suffixLength == Constants.SYMBOL_TABLE_PROPERTY.length() &&
+ propertyId.endsWith(Constants.SYMBOL_TABLE_PROPERTY)) {
+ fSymbolTable = (SymbolTable)value;
+ return;
+ }
+ if (suffixLength == Constants.ERROR_REPORTER_PROPERTY.length() &&
+ propertyId.endsWith(Constants.ERROR_REPORTER_PROPERTY)) {
+ fErrorReporter = (XMLErrorReporter)value;
+ return;
+ }
+ if (suffixLength == Constants.ENTITY_RESOLVER_PROPERTY.length() &&
+ propertyId.endsWith(Constants.ENTITY_RESOLVER_PROPERTY)) {
+ fEntityResolver = (XMLEntityResolver)value;
+ return;
+ }
+ if (suffixLength == Constants.BUFFER_SIZE_PROPERTY.length() &&
+ propertyId.endsWith(Constants.BUFFER_SIZE_PROPERTY)) {
+ Integer bufferSize = (Integer)value;
+ if (bufferSize != null &&
+ bufferSize.intValue() > DEFAULT_XMLDECL_BUFFER_SIZE) {
+ fBufferSize = bufferSize.intValue();
+ fEntityScanner.setBufferSize(fBufferSize);
+ fSmallByteBufferPool.setBufferSize(fBufferSize);
+ fLargeByteBufferPool.setBufferSize(fBufferSize << 1);
+ fCharacterBufferPool.setExternalBufferSize(fBufferSize);
+ }
+ }
+ if (suffixLength == Constants.SECURITY_MANAGER_PROPERTY.length() &&
+ propertyId.endsWith(Constants.SECURITY_MANAGER_PROPERTY)) {
+ fSecurityManager = (SecurityManager)value;
+ fEntityExpansionLimit = (fSecurityManager != null)?fSecurityManager.getEntityExpansionLimit():0;
+ }
+ }
+
+ } // setProperty(String,Object)
+
+ /**
+ * Returns the default state for a feature, or null if this
+ * component does not want to report a default value for this
+ * feature.
+ *
+ * @param featureId The feature identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Boolean getFeatureDefault(String featureId) {
+ for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
+ if (RECOGNIZED_FEATURES[i].equals(featureId)) {
+ return FEATURE_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getFeatureDefault(String):Boolean
+
+ /**
+ * Returns the default state for a property, or null if this
+ * component does not want to report a default value for this
+ * property.
+ *
+ * @param propertyId The property identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Object getPropertyDefault(String propertyId) {
+ for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
+ if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
+ return PROPERTY_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getPropertyDefault(String):Object
+
+ //
+ // Public static methods
+ //
+
+ // current value of the "user.dir" property
+ private static String gUserDir;
+ // cached URI object for the current value of the escaped "user.dir" property stored as a URI
+ private static URI gUserDirURI;
+ // which ASCII characters need to be escaped
+ private static final boolean gNeedEscaping[] = new boolean[128];
+ // the first hex character if a character needs to be escaped
+ private static final char gAfterEscaping1[] = new char[128];
+ // the second hex character if a character needs to be escaped
+ private static final char gAfterEscaping2[] = new char[128];
+ private static final char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+ // initialize the above 3 arrays
+ static {
+ for (int i = 0; i <= 0x1f; i++) {
+ gNeedEscaping[i] = true;
+ gAfterEscaping1[i] = gHexChs[i >> 4];
+ gAfterEscaping2[i] = gHexChs[i & 0xf];
+ }
+ gNeedEscaping[0x7f] = true;
+ gAfterEscaping1[0x7f] = '7';
+ gAfterEscaping2[0x7f] = 'F';
+ char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}',
+ '|', '\\', '^', '~', '[', ']', '`'};
+ int len = escChs.length;
+ char ch;
+ for (int i = 0; i < len; i++) {
+ ch = escChs[i];
+ gNeedEscaping[ch] = true;
+ gAfterEscaping1[ch] = gHexChs[ch >> 4];
+ gAfterEscaping2[ch] = gHexChs[ch & 0xf];
+ }
+ }
+
+ private static PrivilegedAction GET_USER_DIR_SYSTEM_PROPERTY = new PrivilegedAction() {
+ public Object run() {
+ return System.getProperty("user.dir");
+ }
+ };
+
+ // To escape the "user.dir" system property, by using %HH to represent
+ // special ASCII characters: 0x00~0x1F, 0x7F, ' ', '<', '>', '#', '%'
+ // and '"'. It's a static method, so needs to be synchronized.
+ // this method looks heavy, but since the system property isn't expected
+ // to change often, so in most cases, we only need to return the URI
+ // that was escaped before.
+ // According to the URI spec, non-ASCII characters (whose value >= 128)
+ // need to be escaped too.
+ // REVISIT: don't know how to escape non-ASCII characters, especially
+ // which encoding to use. Leave them for now.
+ private static synchronized URI getUserDir() throws URI.MalformedURIException {
+ // get the user.dir property
+ String userDir = "";
+ try {
+ userDir = (String) AccessController.doPrivileged(GET_USER_DIR_SYSTEM_PROPERTY);
+ }
+ catch (SecurityException se) {}
+
+ // return empty string if property value is empty string.
+ if (userDir.length() == 0)
+ return new URI("file", "", "", null, null);
+
+ // compute the new escaped value if the new property value doesn't
+ // match the previous one
+ if (gUserDirURI != null && userDir.equals(gUserDir)) {
+ return gUserDirURI;
+ }
+
+ // record the new value as the global property value
+ gUserDir = userDir;
+
+ char separator = java.io.File.separatorChar;
+ userDir = userDir.replace(separator, '/');
+
+ int len = userDir.length(), ch;
+ StringBuffer buffer = new StringBuffer(len*3);
+ // change C:/blah to /C:/blah
+ if (len >= 2 && userDir.charAt(1) == ':') {
+ ch = Character.toUpperCase(userDir.charAt(0));
+ if (ch >= 'A' && ch <= 'Z') {
+ buffer.append('/');
+ }
+ }
+
+ // for each character in the path
+ int i = 0;
+ for (; i < len; i++) {
+ ch = userDir.charAt(i);
+ // if it's not an ASCII character, break here, and use UTF-8 encoding
+ if (ch >= 128)
+ break;
+ if (gNeedEscaping[ch]) {
+ buffer.append('%');
+ buffer.append(gAfterEscaping1[ch]);
+ buffer.append(gAfterEscaping2[ch]);
+ // record the fact that it's escaped
+ }
+ else {
+ buffer.append((char)ch);
+ }
+ }
+
+ // we saw some non-ascii character
+ if (i < len) {
+ // get UTF-8 bytes for the remaining sub-string
+ byte[] bytes = null;
+ byte b;
+ try {
+ bytes = userDir.substring(i).getBytes("UTF-8");
+ } catch (java.io.UnsupportedEncodingException e) {
+ // should never happen
+ return new URI("file", "", userDir, null, null);
+ }
+ len = bytes.length;
+
+ // for each byte
+ for (i = 0; i < len; i++) {
+ b = bytes[i];
+ // for non-ascii character: make it positive, then escape
+ if (b < 0) {
+ ch = b + 256;
+ buffer.append('%');
+ buffer.append(gHexChs[ch >> 4]);
+ buffer.append(gHexChs[ch & 0xf]);
+ }
+ else if (gNeedEscaping[b]) {
+ buffer.append('%');
+ buffer.append(gAfterEscaping1[b]);
+ buffer.append(gAfterEscaping2[b]);
+ }
+ else {
+ buffer.append((char)b);
+ }
+ }
+ }
+
+ // change blah/blah to blah/blah/
+ if (!userDir.endsWith("/"))
+ buffer.append('/');
+
+ gUserDirURI = new URI("file", "", buffer.toString(), null, null);
+
+ return gUserDirURI;
+ }
+
+ /**
+ * Absolutizes a URI using the current value
+ * of the "user.dir" property as the base URI. If
+ * the URI is already absolute, this is a no-op.
+ *
+ * @param uri the URI to absolutize
+ */
+ public static void absolutizeAgainstUserDir(URI uri)
+ throws URI.MalformedURIException {
+ uri.absolutize(getUserDir());
+ }
+
+ /**
+ * Expands a system id and returns the system id as a URI, if
+ * it can be expanded. A return value of null means that the
+ * identifier is already expanded. An exception thrown
+ * indicates a failure to expand the id.
+ *
+ * @param systemId The systemId to be expanded.
+ *
+ * @return Returns the URI string representing the expanded system
+ * identifier. A null value indicates that the given
+ * system identifier is already expanded.
+ *
+ */
+ public static String expandSystemId(String systemId, String baseSystemId,
+ boolean strict)
+ throws URI.MalformedURIException {
+
+ // check if there is a system id before
+ // trying to expand it.
+ if (systemId == null) {
+ return null;
+ }
+
+ // system id has to be a valid URI
+ if (strict) {
+ return expandSystemIdStrictOn(systemId, baseSystemId);
+ }
+
+ // Assume the URIs are well-formed. If it turns out they're not, try fixing them up.
+ try {
+ return expandSystemIdStrictOff(systemId, baseSystemId);
+ }
+ catch (URI.MalformedURIException e) {
+ // continue on...
+ }
+
+ // check for bad parameters id
+ if (systemId.length() == 0) {
+ return systemId;
+ }
+
+ // normalize id
+ String id = fixURI(systemId);
+
+ // normalize base
+ URI base = null;
+ URI uri = null;
+ try {
+ if (baseSystemId == null || baseSystemId.length() == 0 ||
+ baseSystemId.equals(systemId)) {
+ base = getUserDir();
+ }
+ else {
+ try {
+ base = new URI(fixURI(baseSystemId).trim());
+ }
+ catch (URI.MalformedURIException e) {
+ if (baseSystemId.indexOf(':') != -1) {
+ // for xml schemas we might have baseURI with
+ // a specified drive
+ base = new URI("file", "", fixURI(baseSystemId).trim(), null, null);
+ }
+ else {
+ base = new URI(getUserDir(), fixURI(baseSystemId));
+ }
+ }
+ }
+ // expand id
+ uri = new URI(base, id.trim());
+ }
+ catch (Exception e) {
+ // let it go through
+
+ }
+
+ if (uri == null) {
+ return systemId;
+ }
+ return uri.toString();
+
+ } // expandSystemId(String,String,boolean):String
+
+ /**
+ * Helper method for expandSystemId(String,String,boolean):String
+ */
+ private static String expandSystemIdStrictOn(String systemId, String baseSystemId)
+ throws URI.MalformedURIException {
+
+ URI systemURI = new URI(systemId, true);
+ // If it's already an absolute one, return it
+ if (systemURI.isAbsoluteURI()) {
+ return systemId;
+ }
+
+ // If there isn't a base URI, use the working directory
+ URI baseURI = null;
+ if (baseSystemId == null || baseSystemId.length() == 0) {
+ baseURI = getUserDir();
+ }
+ else {
+ baseURI = new URI(baseSystemId, true);
+ if (!baseURI.isAbsoluteURI()) {
+ // assume "base" is also a relative uri
+ baseURI.absolutize(getUserDir());
+ }
+ }
+
+ // absolutize the system identifier using the base URI
+ systemURI.absolutize(baseURI);
+
+ // return the string rep of the new uri (an absolute one)
+ return systemURI.toString();
+
+ // if any exception is thrown, it'll get thrown to the caller.
+
+ } // expandSystemIdStrictOn(String,String):String
+
+ /**
+ * Helper method for expandSystemId(String,String,boolean):String
+ */
+ private static String expandSystemIdStrictOff(String systemId, String baseSystemId)
+ throws URI.MalformedURIException {
+
+ URI systemURI = new URI(systemId, true);
+ // If it's already an absolute one, return it
+ if (systemURI.isAbsoluteURI()) {
+ if (systemURI.getScheme().length() > 1) {
+ return systemId;
+ }
+ /**
+ * If the scheme's length is only one character,
+ * it's likely that this was intended as a file
+ * path. Fixing this up in expandSystemId to
+ * maintain backwards compatibility.
+ */
+ throw new URI.MalformedURIException();
+ }
+
+ // If there isn't a base URI, use the working directory
+ URI baseURI = null;
+ if (baseSystemId == null || baseSystemId.length() == 0) {
+ baseURI = getUserDir();
+ }
+ else {
+ baseURI = new URI(baseSystemId, true);
+ if (!baseURI.isAbsoluteURI()) {
+ // assume "base" is also a relative uri
+ baseURI.absolutize(getUserDir());
+ }
+ }
+
+ // absolutize the system identifier using the base URI
+ systemURI.absolutize(baseURI);
+
+ // return the string rep of the new uri (an absolute one)
+ return systemURI.toString();
+
+ // if any exception is thrown, it'll get thrown to the caller.
+
+ } // expandSystemIdStrictOff(String,String):String
+
+ public static OutputStream createOutputStream(String uri) throws IOException {
+ // URI was specified. Handle relative URIs.
+ final String expanded = XMLEntityManager.expandSystemId(uri, null, true);
+ final URL url = new URL(expanded != null ? expanded : uri);
+ OutputStream out = null;
+ String protocol = url.getProtocol();
+ String host = url.getHost();
+ // Use FileOutputStream if this URI is for a local file.
+ if (protocol.equals("file")
+ && (host == null || host.length() == 0 || host.equals("localhost"))) {
+ File file = new File(getPathWithoutEscapes(url.getPath()));
+ if (!file.exists()) {
+ File parent = file.getParentFile();
+ if (parent != null && !parent.exists()) {
+ parent.mkdirs();
+ }
+ }
+ out = new FileOutputStream(file);
+ }
+ // Try to write to some other kind of URI. Some protocols
+ // won't support this, though HTTP should work.
+ else {
+ URLConnection urlCon = url.openConnection();
+ urlCon.setDoInput(false);
+ urlCon.setDoOutput(true);
+ urlCon.setUseCaches(false); // Enable tunneling.
+ if (urlCon instanceof HttpURLConnection) {
+ // The DOM L3 REC says if we are writing to an HTTP URI
+ // it is to be done with an HTTP PUT.
+ HttpURLConnection httpCon = (HttpURLConnection) urlCon;
+ httpCon.setRequestMethod("PUT");
+ }
+ out = urlCon.getOutputStream();
+ }
+ return out;
+ }
+
+ private static String getPathWithoutEscapes(String origPath) {
+ if (origPath != null && origPath.length() != 0 && origPath.indexOf('%') != -1) {
+ // Locate the escape characters
+ StringTokenizer tokenizer = new StringTokenizer(origPath, "%");
+ StringBuffer result = new StringBuffer(origPath.length());
+ int size = tokenizer.countTokens();
+ result.append(tokenizer.nextToken());
+ for(int i = 1; i < size; ++i) {
+ String token = tokenizer.nextToken();
+ // Decode the 2 digit hexadecimal number following % in '%nn'
+ result.append((char)Integer.valueOf(token.substring(0, 2), 16).intValue());
+ result.append(token.substring(2));
+ }
+ return result.toString();
+ }
+ return origPath;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * Ends an entity.
+ *
+ * @throws XNIException Thrown by entity handler to signal an error.
+ */
+ void endEntity() throws XNIException {
+
+ // call handler
+ if (DEBUG_BUFFER) {
+ System.out.print("(endEntity: ");
+ print(fCurrentEntity);
+ System.out.println();
+ }
+ if (fEntityHandler != null) {
+ fEntityHandler.endEntity(fCurrentEntity.name, null);
+ }
+
+ // Close the reader for the current entity once we're
+ // done with it, and remove it from our stack. If parsing
+ // is halted at some point, the rest of the readers on
+ // the stack will be closed during cleanup.
+ try {
+ fCurrentEntity.reader.close();
+ }
+ catch (IOException e) {
+ // ignore
+ }
+ // REVISIT: We should never encounter underflow if the calls
+ // to startEntity and endEntity are balanced, but guard
+ // against the EmptyStackException for now. -- mrglavas
+ if (!fReaderStack.isEmpty()) {
+ fReaderStack.pop();
+ }
+
+ // Release the character buffer back to the pool for reuse
+ fCharacterBufferPool.returnBuffer(fCurrentEntity.fCharacterBuffer);
+
+ // Release the byte buffer back to the pool for reuse
+ if (fCurrentEntity.fByteBuffer != null) {
+ if (fCurrentEntity.fByteBuffer.length == fBufferSize) {
+ fSmallByteBufferPool.returnBuffer(fCurrentEntity.fByteBuffer);
+ }
+ else {
+ fLargeByteBufferPool.returnBuffer(fCurrentEntity.fByteBuffer);
+ }
+ }
+
+ // Pop entity stack.
+ fCurrentEntity = fEntityStack.size() > 0
+ ? (ScannedEntity)fEntityStack.pop() : null;
+ fEntityScanner.setCurrentEntity(fCurrentEntity);
+ if (DEBUG_BUFFER) {
+ System.out.print(")endEntity: ");
+ print(fCurrentEntity);
+ System.out.println();
+ }
+
+ } // endEntity()
+
+ /**
+ * Returns the IANA encoding name that is auto-detected from
+ * the bytes specified, with the endian-ness of that encoding where appropriate.
+ *
+ * @param b4 The first four bytes of the input.
+ * @param count The number of bytes actually read.
+ * @return an instance of EncodingInfo which represents the auto-detected encoding.
+ */
+ protected EncodingInfo getEncodingInfo(byte[] b4, int count) {
+
+ if (count < 2) {
+ return EncodingInfo.UTF_8;
+ }
+
+ // UTF-16, with BOM
+ int b0 = b4[0] & 0xFF;
+ int b1 = b4[1] & 0xFF;
+ if (b0 == 0xFE && b1 == 0xFF) {
+ // UTF-16, big-endian
+ return EncodingInfo.UTF_16_BIG_ENDIAN_WITH_BOM;
+ }
+ if (b0 == 0xFF && b1 == 0xFE) {
+ // UTF-16, little-endian
+ return EncodingInfo.UTF_16_LITTLE_ENDIAN_WITH_BOM;
+ }
+
+ // default to UTF-8 if we don't have enough bytes to make a
+ // good determination of the encoding
+ if (count < 3) {
+ return EncodingInfo.UTF_8;
+ }
+
+ // UTF-8 with a BOM
+ int b2 = b4[2] & 0xFF;
+ if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
+ return EncodingInfo.UTF_8_WITH_BOM;
+ }
+
+ // default to UTF-8 if we don't have enough bytes to make a
+ // good determination of the encoding
+ if (count < 4) {
+ return EncodingInfo.UTF_8;
+ }
+
+ // other encodings
+ int b3 = b4[3] & 0xFF;
+ if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
+ // UCS-4, big endian (1234)
+ return EncodingInfo.UCS_4_BIG_ENDIAN;
+ }
+ if (b0 == 0x3C && b1 == 0x00 && b2 == 0x00 && b3 == 0x00) {
+ // UCS-4, little endian (4321)
+ return EncodingInfo.UCS_4_LITTLE_ENDIAN;
+ }
+ if (b0 == 0x00 && b1 == 0x00 && b2 == 0x3C && b3 == 0x00) {
+ // UCS-4, unusual octet order (2143)
+ // REVISIT: What should this be?
+ return EncodingInfo.UCS_4_UNUSUAL_BYTE_ORDER;
+ }
+ if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x00) {
+ // UCS-4, unusual octect order (3412)
+ // REVISIT: What should this be?
+ return EncodingInfo.UCS_4_UNUSUAL_BYTE_ORDER;
+ }
+ if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
+ // UTF-16, big-endian, no BOM
+ // (or could turn out to be UCS-2...
+ // REVISIT: What should this be?
+ return EncodingInfo.UTF_16_BIG_ENDIAN;
+ }
+ if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
+ // UTF-16, little-endian, no BOM
+ // (or could turn out to be UCS-2...
+ return EncodingInfo.UTF_16_LITTLE_ENDIAN;
+ }
+ if (b0 == 0x4C && b1 == 0x6F && b2 == 0xA7 && b3 == 0x94) {
+ // EBCDIC
+ // a la xerces1, return CP037 instead of EBCDIC here
+ return EncodingInfo.EBCDIC;
+ }
+
+ // default encoding
+ return EncodingInfo.UTF_8;
+
+ } // getEncodingName(byte[],int):Object[]
+
+ /**
+ * Creates a reader capable of reading the given input stream in
+ * the specified encoding.
+ *
+ * @param inputStream The input stream.
+ * @param encoding The encoding name that the input stream is
+ * encoded using. If the user has specified that
+ * Java encoding names are allowed, then the
+ * encoding name may be a Java encoding name;
+ * otherwise, it is an ianaEncoding name.
+ * @param isBigEndian For encodings (like uCS-4), whose names cannot
+ * specify a byte order, this tells whether the order is bigEndian. Null means
+ * unknown or not relevant.
+ *
+ * @return Returns a reader.
+ */
+ protected Reader createReader(InputStream inputStream, String encoding, Boolean isBigEndian)
+ throws IOException {
+
+ // if the encoding is UTF-8 use the optimized UTF-8 reader
+ if (encoding == "UTF-8" || encoding == null) {
+ return createUTF8Reader(inputStream);
+ }
+
+ // If the encoding is UTF-16 use the optimized UTF-16 reader
+ if (encoding == "UTF-16" && isBigEndian != null) {
+ return createUTF16Reader(inputStream, isBigEndian.booleanValue());
+ }
+
+ // try to use an optimized reader
+ String ENCODING = encoding.toUpperCase(Locale.ENGLISH);
+ if (ENCODING.equals("UTF-8")) {
+ return createUTF8Reader(inputStream);
+ }
+ if (ENCODING.equals("UTF-16BE")) {
+ return createUTF16Reader(inputStream, true);
+ }
+ if (ENCODING.equals("UTF-16LE")) {
+ return createUTF16Reader(inputStream, false);
+ }
+ if (ENCODING.equals("ISO-10646-UCS-4")) {
+ if(isBigEndian != null) {
+ boolean isBE = isBigEndian.booleanValue();
+ if(isBE) {
+ return new UCSReader(inputStream, UCSReader.UCS4BE);
+ } else {
+ return new UCSReader(inputStream, UCSReader.UCS4LE);
+ }
+ } else {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "EncodingByteOrderUnsupported",
+ new Object[] { encoding },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ if (ENCODING.equals("ISO-10646-UCS-2")) {
+ if(isBigEndian != null) { // should never happen with this encoding...
+ boolean isBE = isBigEndian.booleanValue();
+ if(isBE) {
+ return new UCSReader(inputStream, UCSReader.UCS2BE);
+ } else {
+ return new UCSReader(inputStream, UCSReader.UCS2LE);
+ }
+ } else {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "EncodingByteOrderUnsupported",
+ new Object[] { encoding },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+
+ // check for valid name
+ boolean validIANA = XMLChar.isValidIANAEncoding(encoding);
+ boolean validJava = XMLChar.isValidJavaEncoding(encoding);
+ if (!validIANA || (fAllowJavaEncodings && !validJava)) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "EncodingDeclInvalid",
+ new Object[] { encoding },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ // NOTE: AndyH suggested that, on failure, we use ISO Latin 1
+ // because every byte is a valid ISO Latin 1 character.
+ // It may not translate correctly but if we failed on
+ // the encoding anyway, then we're expecting the content
+ // of the document to be bad. This will just prevent an
+ // invalid UTF-8 sequence to be detected. This is only
+ // important when continue-after-fatal-error is turned
+ // on. -Ac
+ return createLatin1Reader(inputStream);
+ }
+
+ // try to use a Java reader
+ String javaEncoding = EncodingMap.getIANA2JavaMapping(ENCODING);
+ if (javaEncoding == null) {
+ if (fAllowJavaEncodings) {
+ javaEncoding = encoding;
+ }
+ else {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "EncodingDeclInvalid",
+ new Object[] { encoding },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ // see comment above.
+ return createLatin1Reader(inputStream);
+ }
+ }
+ else if (javaEncoding.equals("ASCII")) {
+ return createASCIIReader(inputStream);
+ }
+ else if (javaEncoding.equals("ISO8859_1")) {
+ return createLatin1Reader(inputStream);
+ }
+ if (DEBUG_ENCODINGS) {
+ System.out.print("$$$ creating Java InputStreamReader: encoding="+javaEncoding);
+ if (javaEncoding == encoding) {
+ System.out.print(" (IANA encoding)");
+ }
+ System.out.println();
+ }
+ return new InputStreamReader(inputStream, javaEncoding);
+
+ } // createReader(InputStream,String, Boolean): Reader
+
+ /** Create a new UTF-8 reader from the InputStream. **/
+ private Reader createUTF8Reader(InputStream stream) {
+ if (DEBUG_ENCODINGS) {
+ System.out.println("$$$ creating UTF8Reader");
+ }
+ if (fTempByteBuffer == null) {
+ fTempByteBuffer = fSmallByteBufferPool.getBuffer();
+ }
+ return new UTF8Reader(stream,
+ fTempByteBuffer,
+ fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN),
+ fErrorReporter.getLocale());
+ } // createUTF8Reader(InputStream):Reader
+
+ /** Create a new UTF-16 reader from the InputStream. **/
+ private Reader createUTF16Reader(InputStream stream, boolean isBigEndian) {
+ if (DEBUG_ENCODINGS) {
+ System.out.println("$$$ creating UTF16Reader");
+ }
+ if (fTempByteBuffer == null) {
+ fTempByteBuffer = fLargeByteBufferPool.getBuffer();
+ }
+ // The cached buffer is too small, we need a larger one.
+ else if (fTempByteBuffer.length == fBufferSize) {
+ fSmallByteBufferPool.returnBuffer(fTempByteBuffer);
+ fTempByteBuffer = fLargeByteBufferPool.getBuffer();
+ }
+ return new UTF16Reader(stream,
+ fTempByteBuffer,
+ isBigEndian,
+ fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN),
+ fErrorReporter.getLocale());
+ } // createUTF16Reader(InputStream):Reader
+
+ /** Create a new ASCII reader from the InputStream. **/
+ private Reader createASCIIReader(InputStream stream) {
+ if (DEBUG_ENCODINGS) {
+ System.out.println("$$$ creating ASCIIReader");
+ }
+ if (fTempByteBuffer == null) {
+ fTempByteBuffer = fSmallByteBufferPool.getBuffer();
+ }
+ return new ASCIIReader(stream,
+ fTempByteBuffer,
+ fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN),
+ fErrorReporter.getLocale());
+ } // createASCIIReader(InputStream):Reader
+
+ /** Create a new ISO-8859-1 reader from the InputStream. **/
+ private Reader createLatin1Reader(InputStream stream) {
+ if (DEBUG_ENCODINGS) {
+ System.out.println("$$$ creating Latin1Reader");
+ }
+ if (fTempByteBuffer == null) {
+ fTempByteBuffer = fSmallByteBufferPool.getBuffer();
+ }
+ return new Latin1Reader(stream, fTempByteBuffer);
+ } // createLatin1Reader(InputStream):Reader
+
+ //
+ // Protected static methods
+ //
+
+ /**
+ * Fixes a platform dependent filename to standard URI form.
+ *
+ * @param str The string to fix.
+ *
+ * @return Returns the fixed URI string.
+ */
+ protected static String fixURI(String str) {
+
+ // handle platform dependent strings
+ str = str.replace(java.io.File.separatorChar, '/');
+
+ StringBuffer sb = null;
+
+ // Windows fix
+ if (str.length() >= 2) {
+ char ch1 = str.charAt(1);
+ // change "C:blah" to "file:///C:blah"
+ if (ch1 == ':') {
+ char ch0 = Character.toUpperCase(str.charAt(0));
+ if (ch0 >= 'A' && ch0 <= 'Z') {
+ sb = new StringBuffer(str.length() + 8);
+ sb.append("file:///");
+ }
+ }
+ // change "//blah" to "file://blah"
+ else if (ch1 == '/' && str.charAt(0) == '/') {
+ sb = new StringBuffer(str.length() + 5);
+ sb.append("file:");
+ }
+ }
+
+ int pos = str.indexOf(' ');
+ // there is no space in the string
+ // we just append "str" to the end of sb
+ if (pos < 0) {
+ if (sb != null) {
+ sb.append(str);
+ str = sb.toString();
+ }
+ }
+ // otherwise, convert all ' ' to "%20".
+ // Note: the following algorithm might not be very performant,
+ // but people who want to use invalid URI's have to pay the price.
+ else {
+ if (sb == null)
+ sb = new StringBuffer(str.length());
+ // put characters before ' ' into the string buffer
+ for (int i = 0; i < pos; i++)
+ sb.append(str.charAt(i));
+ // and %20 for the space
+ sb.append("%20");
+ // for the remamining part, also convert ' ' to "%20".
+ for (int i = pos+1; i < str.length(); i++) {
+ if (str.charAt(i) == ' ')
+ sb.append("%20");
+ else
+ sb.append(str.charAt(i));
+ }
+ str = sb.toString();
+ }
+
+ // done
+ return str;
+
+ } // fixURI(String):String
+
+ //
+ // Package visible methods
+ //
+
+ /**
+ * Returns the hashtable of declared entities.
+ *
+ * REVISIT:
+ * This should be done the "right" way by designing a better way to
+ * enumerate the declared entities. For now, this method is needed
+ * by the constructor that takes an XMLEntityManager parameter.
+ */
+ Hashtable getDeclaredEntities() {
+ return fEntities;
+ } // getDeclaredEntities():Hashtable
+
+ /** Prints the contents of the buffer. */
+ static final void print(ScannedEntity currentEntity) {
+ if (DEBUG_BUFFER) {
+ if (currentEntity != null) {
+ System.out.print('[');
+ System.out.print(currentEntity.count);
+ System.out.print(' ');
+ System.out.print(currentEntity.position);
+ if (currentEntity.count > 0) {
+ System.out.print(" \"");
+ for (int i = 0; i < currentEntity.count; i++) {
+ if (i == currentEntity.position) {
+ System.out.print('^');
+ }
+ char c = currentEntity.ch[i];
+ switch (c) {
+ case '\n': {
+ System.out.print("\\n");
+ break;
+ }
+ case '\r': {
+ System.out.print("\\r");
+ break;
+ }
+ case '\t': {
+ System.out.print("\\t");
+ break;
+ }
+ case '\\': {
+ System.out.print("\\\\");
+ break;
+ }
+ default: {
+ System.out.print(c);
+ }
+ }
+ }
+ if (currentEntity.position == currentEntity.count) {
+ System.out.print('^');
+ }
+ System.out.print('"');
+ }
+ System.out.print(']');
+ System.out.print(" @ ");
+ System.out.print(currentEntity.lineNumber);
+ System.out.print(',');
+ System.out.print(currentEntity.columnNumber);
+ }
+ else {
+ System.out.print("*NO CURRENT ENTITY*");
+ }
+ }
+ } // print(ScannedEntity)
+
+ //
+ // Classes
+ //
+
+ /**
+ * Entity information.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ */
+ public static abstract class Entity {
+
+ //
+ // Data
+ //
+
+ /** Entity name. */
+ public String name;
+
+ // whether this entity's declaration was found in the internal
+ // or external subset
+ public boolean inExternalSubset;
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public Entity() {
+ clear();
+ } // ()
+
+ /** Constructs an entity. */
+ public Entity(String name, boolean inExternalSubset) {
+ this.name = name;
+ this.inExternalSubset = inExternalSubset;
+ } // (String)
+
+ //
+ // Public methods
+ //
+
+ /** Returns true if this entity was declared in the external subset. */
+ public boolean isEntityDeclInExternalSubset () {
+ return inExternalSubset;
+ }
+
+ /** Returns true if this is an external entity. */
+ public abstract boolean isExternal();
+
+ /** Returns true if this is an unparsed entity. */
+ public abstract boolean isUnparsed();
+
+ /** Clears the entity. */
+ public void clear() {
+ name = null;
+ inExternalSubset = false;
+ } // clear()
+
+ /** Sets the values of the entity. */
+ public void setValues(Entity entity) {
+ name = entity.name;
+ inExternalSubset = entity.inExternalSubset;
+ } // setValues(Entity)
+
+ } // class Entity
+
+ /**
+ * Internal entity.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ */
+ protected static class InternalEntity
+ extends Entity {
+
+ //
+ // Data
+ //
+
+ /** Text value of entity. */
+ public String text;
+
+ /** Count of direct and indirect references to parameter entities in the value of the entity. */
+ public int paramEntityRefs;
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public InternalEntity() {
+ clear();
+ } // ()
+
+ /** Constructs an internal entity. */
+ public InternalEntity(String name, String text, boolean inExternalSubset) {
+ super(name,inExternalSubset);
+ this.text = text;
+ } // (String,String)
+
+ /** Constructs an internal entity. */
+ public InternalEntity(String name, String text, boolean inExternalSubset, int paramEntityRefs) {
+ this(name, text, inExternalSubset);
+ this.paramEntityRefs = paramEntityRefs;
+ } // (String,String,int)
+
+ //
+ // Entity methods
+ //
+
+ /** Returns true if this is an external entity. */
+ public final boolean isExternal() {
+ return false;
+ } // isExternal():boolean
+
+ /** Returns true if this is an unparsed entity. */
+ public final boolean isUnparsed() {
+ return false;
+ } // isUnparsed():boolean
+
+ /** Clears the entity. */
+ public void clear() {
+ super.clear();
+ text = null;
+ } // clear()
+
+ /** Sets the values of the entity. */
+ public void setValues(Entity entity) {
+ super.setValues(entity);
+ text = null;
+ } // setValues(Entity)
+
+ /** Sets the values of the entity. */
+ public void setValues(InternalEntity entity) {
+ super.setValues(entity);
+ text = entity.text;
+ } // setValues(InternalEntity)
+
+ } // class InternalEntity
+
+ /**
+ * External entity.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ */
+ protected static class ExternalEntity
+ extends Entity {
+
+ //
+ // Data
+ //
+
+ /** container for all relevant entity location information. */
+ public XMLResourceIdentifier entityLocation;
+
+ /** Notation name for unparsed entity. */
+ public String notation;
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public ExternalEntity() {
+ clear();
+ } // ()
+
+ /** Constructs an internal entity. */
+ public ExternalEntity(String name, XMLResourceIdentifier entityLocation,
+ String notation, boolean inExternalSubset) {
+ super(name,inExternalSubset);
+ this.entityLocation = entityLocation;
+ this.notation = notation;
+ } // (String,XMLResourceIdentifier, String)
+
+ //
+ // Entity methods
+ //
+
+ /** Returns true if this is an external entity. */
+ public final boolean isExternal() {
+ return true;
+ } // isExternal():boolean
+
+ /** Returns true if this is an unparsed entity. */
+ public final boolean isUnparsed() {
+ return notation != null;
+ } // isUnparsed():boolean
+
+ /** Clears the entity. */
+ public void clear() {
+ super.clear();
+ entityLocation = null;
+ notation = null;
+ } // clear()
+
+ /** Sets the values of the entity. */
+ public void setValues(Entity entity) {
+ super.setValues(entity);
+ entityLocation = null;
+ notation = null;
+ } // setValues(Entity)
+
+ /** Sets the values of the entity. */
+ public void setValues(ExternalEntity entity) {
+ super.setValues(entity);
+ entityLocation = entity.entityLocation;
+ notation = entity.notation;
+ } // setValues(ExternalEntity)
+
+ } // class ExternalEntity
+
+ /**
+ * Entity state.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ */
+ public class ScannedEntity
+ extends Entity {
+
+ //
+ // Data
+ //
+
+ // i/o
+
+ /** Input stream. */
+ public InputStream stream;
+
+ /** Reader. */
+ public Reader reader;
+
+ // locator information
+
+ /** entity location information */
+ public XMLResourceIdentifier entityLocation;
+
+ /** Line number. */
+ public int lineNumber = 1;
+
+ /** Column number. */
+ public int columnNumber = 1;
+
+ // encoding
+
+ /** Auto-detected encoding. */
+ public String encoding;
+
+ /**
+ * Encoding has been set externally, for example
+ * using a SAX InputSource or a DOM LSInput.
+ */
+ boolean externallySpecifiedEncoding = false;
+
+ // version
+
+ /** XML version. **/
+ public String xmlVersion = "1.0";
+
+ // status
+
+ /** True if in a literal. */
+ public boolean literal;
+
+ // whether this is an external or internal scanned entity
+ public boolean isExternal;
+
+ // buffer
+
+ /** Character buffer. */
+ public char[] ch = null;
+
+ /** Position in character buffer. */
+ public int position;
+
+ /** Base character offset for computing absolute character offset. */
+ public int baseCharOffset;
+
+ /** Start position in character buffer. */
+ public int startPosition;
+
+ /** Count of characters in buffer. */
+ public int count;
+
+ // to allow the reader/inputStream to behave efficiently:
+ public boolean mayReadChunks;
+
+ /** Character buffer container. */
+ private CharacterBuffer fCharacterBuffer;
+
+ /** Byte buffer. */
+ private byte [] fByteBuffer;
+
+ //
+ // Constructors
+ //
+
+ /** Constructs a scanned entity. */
+ public ScannedEntity(String name,
+ XMLResourceIdentifier entityLocation,
+ InputStream stream, Reader reader, byte [] byteBuffer,
+ String encoding, boolean literal, boolean mayReadChunks, boolean isExternal) {
+ super(name,XMLEntityManager.this.fInExternalSubset);
+ this.entityLocation = entityLocation;
+ this.stream = stream;
+ this.reader = reader;
+ this.encoding = encoding;
+ this.literal = literal;
+ this.mayReadChunks = mayReadChunks;
+ this.isExternal = isExternal;
+ this.fCharacterBuffer = fCharacterBufferPool.getBuffer(isExternal);
+ this.ch = fCharacterBuffer.ch;
+ this.fByteBuffer = byteBuffer;
+ } // (StringXMLResourceIdentifier,InputStream,Reader,String,boolean, boolean)
+
+ //
+ // Entity methods
+ //
+
+ /** Returns true if this is an external entity. */
+ public final boolean isExternal() {
+ return isExternal;
+ } // isExternal():boolean
+
+ /** Returns true if this is an unparsed entity. */
+ public final boolean isUnparsed() {
+ return false;
+ } // isUnparsed():boolean
+
+ public void setReader(InputStream stream, String encoding, Boolean isBigEndian) throws IOException {
+ fTempByteBuffer = fByteBuffer;
+ reader = createReader(stream, encoding, isBigEndian);
+ fByteBuffer = fTempByteBuffer;
+ }
+
+ // return the expanded system ID of the
+ // first external entity on the stack, null
+ // otherwise.
+ public String getExpandedSystemId() {
+
+ // search for the first external entity on the stack
+ int size = fEntityStack.size();
+ for (int i = size - 1; i >= 0; --i) {
+ ScannedEntity externalEntity =
+ (ScannedEntity)fEntityStack.elementAt(i);
+
+ if (externalEntity.entityLocation != null &&
+ externalEntity.entityLocation.getExpandedSystemId() != null) {
+ return externalEntity.entityLocation.getExpandedSystemId();
+ }
+ }
+ return null;
+ }
+
+ // return literal systemId of
+ // nearest external entity
+ public String getLiteralSystemId() {
+ // search for the first external entity on the stack
+ int size = fEntityStack.size();
+ for (int i = size - 1; i >= 0; --i) {
+ ScannedEntity externalEntity =
+ (ScannedEntity)fEntityStack.elementAt(i);
+
+ if (externalEntity.entityLocation != null &&
+ externalEntity.entityLocation.getLiteralSystemId() != null) {
+ return externalEntity.entityLocation.getLiteralSystemId();
+ }
+ }
+ return null;
+ }
+
+ // return line number of position in most
+ // recent external entity
+ public int getLineNumber() {
+ // search for the first external entity on the stack
+ int size = fEntityStack.size();
+ for (int i = size - 1; i >= 0 ; --i) {
+ ScannedEntity firstExternalEntity = (ScannedEntity)fEntityStack.elementAt(i);
+ if (firstExternalEntity.isExternal()) {
+ return firstExternalEntity.lineNumber;
+ }
+ }
+ return -1;
+ }
+
+ // return column number of position in most
+ // recent external entity
+ public int getColumnNumber() {
+ // search for the first external entity on the stack
+ int size = fEntityStack.size();
+ for (int i = size - 1; i >= 0; --i) {
+ ScannedEntity firstExternalEntity = (ScannedEntity)fEntityStack.elementAt(i);
+ if (firstExternalEntity.isExternal()) {
+ return firstExternalEntity.columnNumber;
+ }
+ }
+ return -1;
+ }
+
+ // return character offset of position in most
+ // recent external entity
+ public int getCharacterOffset() {
+ // search for the first external entity on the stack
+ int size = fEntityStack.size();
+ for (int i = size - 1; i >= 0; --i) {
+ ScannedEntity firstExternalEntity = (ScannedEntity)fEntityStack.elementAt(i);
+ if (firstExternalEntity.isExternal()) {
+ return firstExternalEntity.baseCharOffset + (firstExternalEntity.position - firstExternalEntity.startPosition);
+ }
+ }
+ return -1;
+ }
+
+ // return encoding of most recent external entity
+ public String getEncoding() {
+ // search for the first external entity on the stack
+ int size = fEntityStack.size();
+ for (int i = size - 1; i >= 0; --i) {
+ ScannedEntity firstExternalEntity = (ScannedEntity)fEntityStack.elementAt(i);
+ if (firstExternalEntity.isExternal()) {
+ return firstExternalEntity.encoding;
+ }
+ }
+ return null;
+ }
+
+ // return xml version of most recent external entity
+ public String getXMLVersion() {
+ // search for the first external entity on the stack
+ int size = fEntityStack.size();
+ for (int i = size - 1; i >= 0; --i) {
+ ScannedEntity firstExternalEntity = (ScannedEntity)fEntityStack.elementAt(i);
+ if (firstExternalEntity.isExternal()) {
+ return firstExternalEntity.xmlVersion;
+ }
+ }
+ return null;
+ }
+
+ /** Returns whether the encoding of this entity was externally specified. **/
+ public boolean isEncodingExternallySpecified() {
+ return externallySpecifiedEncoding;
+ }
+
+ /** Sets whether the encoding of this entity was externally specified. **/
+ public void setEncodingExternallySpecified(boolean value) {
+ externallySpecifiedEncoding = value;
+ }
+
+ //
+ // Object methods
+ //
+
+ /** Returns a string representation of this object. */
+ public String toString() {
+
+ StringBuffer str = new StringBuffer();
+ str.append("name=\"").append(name).append('"');
+ str.append(",ch=");
+ str.append(ch);
+ str.append(",position=").append(position);
+ str.append(",count=").append(count);
+ str.append(",baseCharOffset=").append(baseCharOffset);
+ str.append(",startPosition=").append(startPosition);
+ return str.toString();
+
+ } // toString():String
+
+ } // class ScannedEntity
+
+ /**
+ * Information about auto-detectable encodings.
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ */
+ private static class EncodingInfo {
+
+ /** UTF-8 **/
+ public static final EncodingInfo UTF_8 = new EncodingInfo("UTF-8", null, false);
+
+ /** UTF-8, with BOM **/
+ public static final EncodingInfo UTF_8_WITH_BOM = new EncodingInfo("UTF-8", null, true);
+
+ /** UTF-16, big-endian **/
+ public static final EncodingInfo UTF_16_BIG_ENDIAN = new EncodingInfo("UTF-16BE", "UTF-16", Boolean.TRUE, false);
+
+ /** UTF-16, big-endian with BOM **/
+ public static final EncodingInfo UTF_16_BIG_ENDIAN_WITH_BOM = new EncodingInfo("UTF-16BE", "UTF-16", Boolean.TRUE, true);
+
+ /** UTF-16, little-endian **/
+ public static final EncodingInfo UTF_16_LITTLE_ENDIAN = new EncodingInfo("UTF-16LE", "UTF-16", Boolean.FALSE, false);
+
+ /** UTF-16, little-endian with BOM **/
+ public static final EncodingInfo UTF_16_LITTLE_ENDIAN_WITH_BOM = new EncodingInfo("UTF-16LE", "UTF-16", Boolean.FALSE, true);
+
+ /** UCS-4, big-endian **/
+ public static final EncodingInfo UCS_4_BIG_ENDIAN = new EncodingInfo("ISO-10646-UCS-4", Boolean.TRUE, false);
+
+ /** UCS-4, little-endian **/
+ public static final EncodingInfo UCS_4_LITTLE_ENDIAN = new EncodingInfo("ISO-10646-UCS-4", Boolean.FALSE, false);
+
+ /** UCS-4, unusual byte-order (2143) or (3412) **/
+ public static final EncodingInfo UCS_4_UNUSUAL_BYTE_ORDER = new EncodingInfo("ISO-10646-UCS-4", null, false);
+
+ /** EBCDIC **/
+ public static final EncodingInfo EBCDIC = new EncodingInfo("CP037", null, false);
+
+ public final String autoDetectedEncoding;
+ public final String readerEncoding;
+ public final Boolean isBigEndian;
+ public final boolean hasBOM;
+
+ private EncodingInfo(String autoDetectedEncoding, Boolean isBigEndian, boolean hasBOM) {
+ this(autoDetectedEncoding, autoDetectedEncoding, isBigEndian, hasBOM);
+ } // (String,Boolean,boolean)
+
+ private EncodingInfo(String autoDetectedEncoding, String readerEncoding, Boolean isBigEndian, boolean hasBOM) {
+ this.autoDetectedEncoding = autoDetectedEncoding;
+ this.readerEncoding = readerEncoding;
+ this.isBigEndian = isBigEndian;
+ this.hasBOM = hasBOM;
+ } // (String,String,Boolean,boolean)
+
+ } // class EncodingInfo
+
+ /**
+ * Pool of byte buffers for the java.io.Readers.
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ */
+ private static final class ByteBufferPool {
+
+ private static final int DEFAULT_POOL_SIZE = 3;
+
+ private int fPoolSize;
+ private int fBufferSize;
+ private byte[][] fByteBufferPool;
+ private int fDepth;
+
+ public ByteBufferPool(int bufferSize) {
+ this(DEFAULT_POOL_SIZE, bufferSize);
+ }
+
+ public ByteBufferPool(int poolSize, int bufferSize) {
+ fPoolSize = poolSize;
+ fBufferSize = bufferSize;
+ fByteBufferPool = new byte[fPoolSize][];
+ fDepth = 0;
+ }
+
+ /** Retrieves a byte buffer from the pool. **/
+ public byte[] getBuffer() {
+ return (fDepth > 0) ? fByteBufferPool[--fDepth] : new byte[fBufferSize];
+ }
+
+ /** Returns byte buffer to pool. **/
+ public void returnBuffer(byte[] buffer) {
+ if (fDepth < fByteBufferPool.length) {
+ fByteBufferPool[fDepth++] = buffer;
+ }
+ }
+
+ /** Sets the size of the buffers and dumps the old pool. **/
+ public void setBufferSize(int bufferSize) {
+ fBufferSize = bufferSize;
+ fByteBufferPool = new byte[fPoolSize][];
+ fDepth = 0;
+ }
+ }
+
+ /**
+ * Buffer used in entity manager to reuse character arrays instead
+ * of creating new ones every time.
+ *
+ * @xerces.internal
+ *
+ * @author Ankit Pasricha, IBM
+ */
+ private static final class CharacterBuffer {
+
+ /** character buffer */
+ private final char[] ch;
+
+ /** whether the buffer is for an external or internal scanned entity */
+ private final boolean isExternal;
+
+ public CharacterBuffer(boolean isExternal, int size) {
+ this.isExternal = isExternal;
+ ch = new char[size];
+ }
+ }
+
+ /**
+ * Stores a number of character buffers and provides it to the entity
+ * manager to use when an entity is seen.
+ *
+ * @xerces.internal
+ *
+ * @author Ankit Pasricha, IBM
+ */
+ private static final class CharacterBufferPool {
+
+ private static final int DEFAULT_POOL_SIZE = 3;
+
+ private CharacterBuffer[] fInternalBufferPool;
+ private CharacterBuffer[] fExternalBufferPool;
+
+ private int fExternalBufferSize;
+ private int fInternalBufferSize;
+ private int fPoolSize;
+
+ private int fInternalTop;
+ private int fExternalTop;
+
+ public CharacterBufferPool(int externalBufferSize, int internalBufferSize) {
+ this(DEFAULT_POOL_SIZE, externalBufferSize, internalBufferSize);
+ }
+
+ public CharacterBufferPool(int poolSize, int externalBufferSize, int internalBufferSize) {
+ fExternalBufferSize = externalBufferSize;
+ fInternalBufferSize = internalBufferSize;
+ fPoolSize = poolSize;
+ init();
+ }
+
+ /** Initializes buffer pool. **/
+ private void init() {
+ fInternalBufferPool = new CharacterBuffer[fPoolSize];
+ fExternalBufferPool = new CharacterBuffer[fPoolSize];
+ fInternalTop = -1;
+ fExternalTop = -1;
+ }
+
+ /** Retrieves buffer from pool. **/
+ public CharacterBuffer getBuffer(boolean external) {
+ if (external) {
+ if (fExternalTop > -1) {
+ return (CharacterBuffer)fExternalBufferPool[fExternalTop--];
+ }
+ else {
+ return new CharacterBuffer(true, fExternalBufferSize);
+ }
+ }
+ else {
+ if (fInternalTop > -1) {
+ return (CharacterBuffer)fInternalBufferPool[fInternalTop--];
+ }
+ else {
+ return new CharacterBuffer(false, fInternalBufferSize);
+ }
+ }
+ }
+
+ /** Returns buffer to pool. **/
+ public void returnBuffer(CharacterBuffer buffer) {
+ if (buffer.isExternal) {
+ if (fExternalTop < fExternalBufferPool.length - 1) {
+ fExternalBufferPool[++fExternalTop] = buffer;
+ }
+ }
+ else if (fInternalTop < fInternalBufferPool.length - 1) {
+ fInternalBufferPool[++fInternalTop] = buffer;
+ }
+ }
+
+ /** Sets the size of external buffers and dumps the old pool. **/
+ public void setExternalBufferSize(int bufferSize) {
+ fExternalBufferSize = bufferSize;
+ fExternalBufferPool = new CharacterBuffer[fPoolSize];
+ fExternalTop = -1;
+ }
+ }
+
+ /**
+ * This class wraps the byte inputstreams we're presented with.
+ * We need it because java.io.InputStreams don't provide
+ * functionality to reread processed bytes, and they have a habit
+ * of reading more than one character when you call their read()
+ * methods. This means that, once we discover the true (declared)
+ * encoding of a document, we can neither backtrack to read the
+ * whole doc again nor start reading where we are with a new
+ * reader.
+ *
+ * This class allows rewinding an inputStream by allowing a mark
+ * to be set, and the stream reset to that position. The
+ * class assumes that it needs to read one character per
+ * invocation when it's read() method is inovked, but uses the
+ * underlying InputStream's read(char[], offset length) method--it
+ * won't buffer data read this way!
+ *
+ * @xerces.internal
+ *
+ * @author Neil Graham, IBM
+ * @author Glenn Marcy, IBM
+ */
+ protected final class RewindableInputStream extends InputStream {
+
+ private InputStream fInputStream;
+ private byte[] fData;
+ private int fStartOffset;
+ private int fEndOffset;
+ private int fOffset;
+ private int fLength;
+ private int fMark;
+
+ public RewindableInputStream(InputStream is) {
+ fData = new byte[DEFAULT_XMLDECL_BUFFER_SIZE];
+ fInputStream = is;
+ fStartOffset = 0;
+ fEndOffset = -1;
+ fOffset = 0;
+ fLength = 0;
+ fMark = 0;
+ }
+
+ public void setStartOffset(int offset) {
+ fStartOffset = offset;
+ }
+
+ public void rewind() {
+ fOffset = fStartOffset;
+ }
+
+ public int readAndBuffer() throws IOException {
+ if (fOffset == fData.length) {
+ byte[] newData = new byte[fOffset << 1];
+ System.arraycopy(fData, 0, newData, 0, fOffset);
+ fData = newData;
+ }
+ final int b = fInputStream.read();
+ if (b == -1) {
+ fEndOffset = fOffset;
+ return -1;
+ }
+ fData[fLength++] = (byte)b;
+ fOffset++;
+ return b & 0xff;
+ }
+
+ public int read() throws IOException {
+ if (fOffset < fLength) {
+ return fData[fOffset++] & 0xff;
+ }
+ if (fOffset == fEndOffset) {
+ return -1;
+ }
+ if (fCurrentEntity.mayReadChunks) {
+ return fInputStream.read();
+ }
+ return readAndBuffer();
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ final int bytesLeft = fLength - fOffset;
+ if (bytesLeft == 0) {
+ if (fOffset == fEndOffset) {
+ return -1;
+ }
+ // better get some more for the voracious reader...
+ if (fCurrentEntity.mayReadChunks) {
+ return fInputStream.read(b, off, len);
+ }
+ int returnedVal = readAndBuffer();
+ if (returnedVal == -1) {
+ fEndOffset = fOffset;
+ return -1;
+ }
+ b[off] = (byte)returnedVal;
+ return 1;
+ }
+ if (len < bytesLeft) {
+ if (len <= 0) {
+ return 0;
+ }
+ }
+ else {
+ len = bytesLeft;
+ }
+ if (b != null) {
+ System.arraycopy(fData, fOffset, b, off, len);
+ }
+ fOffset += len;
+ return len;
+ }
+
+ public long skip(long n)
+ throws IOException
+ {
+ int bytesLeft;
+ if (n <= 0) {
+ return 0;
+ }
+ bytesLeft = fLength - fOffset;
+ if (bytesLeft == 0) {
+ if (fOffset == fEndOffset) {
+ return 0;
+ }
+ return fInputStream.skip(n);
+ }
+ if (n <= bytesLeft) {
+ fOffset += n;
+ return n;
+ }
+ fOffset += bytesLeft;
+ if (fOffset == fEndOffset) {
+ return bytesLeft;
+ }
+ n -= bytesLeft;
+ /*
+ * In a manner of speaking, when this class isn't permitting more
+ * than one byte at a time to be read, it is "blocking". The
+ * available() method should indicate how much can be read without
+ * blocking, so while we're in this mode, it should only indicate
+ * that bytes in its buffer are available; otherwise, the result of
+ * available() on the underlying InputStream is appropriate.
+ */
+ return fInputStream.skip(n) + bytesLeft;
+ }
+
+ public int available() throws IOException {
+ final int bytesLeft = fLength - fOffset;
+ if (bytesLeft == 0) {
+ if (fOffset == fEndOffset) {
+ return -1;
+ }
+ return fCurrentEntity.mayReadChunks ? fInputStream.available()
+ : 0;
+ }
+ return bytesLeft;
+ }
+
+ public void mark(int howMuch) {
+ fMark = fOffset;
+ }
+
+ public void reset() {
+ fOffset = fMark;
+ }
+
+ public boolean markSupported() {
+ return true;
+ }
+
+ public void close() throws IOException {
+ if (fInputStream != null) {
+ fInputStream.close();
+ fInputStream = null;
+ }
+ }
+ } // end of RewindableInputStream class
+
+} // class XMLEntityManager
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XMLEntityScanner.java b/resources/xerces2-j-src/org/apache/xerces/impl/XMLEntityScanner.java
new file mode 100644
index 0000000..1e3e404
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XMLEntityScanner.java
@@ -0,0 +1,1794 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.util.Locale;
+
+import org.apache.xerces.impl.io.UCSReader;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.util.XMLStringBuffer;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLLocator;
+import org.apache.xerces.xni.XMLString;
+
+/**
+ * Implements the entity scanner methods.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ * @author Neil Graham, IBM
+ * @version $Id$
+ */
+public class XMLEntityScanner implements XMLLocator {
+
+ // constants
+ private static final boolean DEBUG_ENCODINGS = false;
+ private static final boolean DEBUG_BUFFER = false;
+
+ /**
+ * To signal the end of the document entity, this exception will be thrown.
+ */
+ private static final EOFException END_OF_DOCUMENT_ENTITY = new EOFException() {
+ private static final long serialVersionUID = 980337771224675268L;
+ public Throwable fillInStackTrace() {
+ return this;
+ }
+ };
+
+ //
+ // Data
+ //
+
+ private XMLEntityManager fEntityManager = null;
+ protected XMLEntityManager.ScannedEntity fCurrentEntity = null;
+
+ protected SymbolTable fSymbolTable = null;
+
+ protected int fBufferSize = XMLEntityManager.DEFAULT_BUFFER_SIZE;
+
+ /**
+ * Error reporter. This property identifier is:
+ * http://apache.org/xml/properties/internal/error-reporter
+ */
+ protected XMLErrorReporter fErrorReporter;
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XMLEntityScanner() {
+ } // ()
+
+ //
+ // XMLEntityScanner methods
+ //
+
+ /**
+ * Returns the base system identifier of the currently scanned
+ * entity, or null if none is available.
+ */
+ public final String getBaseSystemId() {
+ return (fCurrentEntity != null && fCurrentEntity.entityLocation != null) ? fCurrentEntity.entityLocation.getExpandedSystemId() : null;
+ } // getBaseSystemId():String
+
+ /**
+ * Sets the encoding of the scanner. This method is used by the
+ * scanners if the XMLDecl or TextDecl line contains an encoding
+ * pseudo-attribute.
+ *
+ * Note: The underlying character reader on the
+ * current entity will be changed to accomodate the new encoding.
+ * However, the new encoding is ignored if the current reader was
+ * not constructed from an input stream (e.g. an external entity
+ * that is resolved directly to the appropriate java.io.Reader
+ * object).
+ *
+ * @param encoding The IANA encoding name of the new encoding.
+ *
+ * @throws IOException Thrown if the new encoding is not supported.
+ *
+ * @see org.apache.xerces.util.EncodingMap
+ */
+ public final void setEncoding(String encoding) throws IOException {
+
+ if (DEBUG_ENCODINGS) {
+ System.out.println("$$$ setEncoding: "+encoding);
+ }
+
+ if (fCurrentEntity.stream != null) {
+ // if the encoding is the same, don't change the reader and
+ // re-use the original reader used by the OneCharReader
+ // NOTE: Besides saving an object, this overcomes deficiencies
+ // in the UTF-16 reader supplied with the standard Java
+ // distribution (up to and including 1.3). The UTF-16
+ // decoder buffers 8K blocks even when only asked to read
+ // a single char! -Ac
+ if (fCurrentEntity.encoding == null ||
+ !fCurrentEntity.encoding.equals(encoding)) {
+ // UTF-16 is a bit of a special case. If the encoding is UTF-16,
+ // and we know the endian-ness, we shouldn't change readers.
+ // If it's ISO-10646-UCS-(2|4), then we'll have to deduce
+ // the endian-ness from the encoding we presently have.
+ if(fCurrentEntity.encoding != null && fCurrentEntity.encoding.startsWith("UTF-16")) {
+ String ENCODING = encoding.toUpperCase(Locale.ENGLISH);
+ if(ENCODING.equals("UTF-16")) return;
+ if(ENCODING.equals("ISO-10646-UCS-4")) {
+ if(fCurrentEntity.encoding.equals("UTF-16BE")) {
+ fCurrentEntity.reader = new UCSReader(fCurrentEntity.stream, UCSReader.UCS4BE);
+ } else {
+ fCurrentEntity.reader = new UCSReader(fCurrentEntity.stream, UCSReader.UCS4LE);
+ }
+ return;
+ }
+ if(ENCODING.equals("ISO-10646-UCS-2")) {
+ if(fCurrentEntity.encoding.equals("UTF-16BE")) {
+ fCurrentEntity.reader = new UCSReader(fCurrentEntity.stream, UCSReader.UCS2BE);
+ } else {
+ fCurrentEntity.reader = new UCSReader(fCurrentEntity.stream, UCSReader.UCS2LE);
+ }
+ return;
+ }
+ }
+ // wrap a new reader around the input stream, changing
+ // the encoding
+ if (DEBUG_ENCODINGS) {
+ System.out.println("$$$ creating new reader from stream: "+
+ fCurrentEntity.stream);
+ }
+ //fCurrentEntity.stream.reset();
+ fCurrentEntity.setReader(fCurrentEntity.stream, encoding, null);
+ fCurrentEntity.encoding = encoding;
+ } else {
+ if (DEBUG_ENCODINGS)
+ System.out.println("$$$ reusing old reader on stream");
+ }
+ }
+
+ } // setEncoding(String)
+
+ /**
+ * Sets the XML version. This method is used by the
+ * scanners to report the value of the version pseudo-attribute
+ * in an XML or text declaration.
+ *
+ * @param xmlVersion the XML version of the current entity
+ */
+ public final void setXMLVersion(String xmlVersion) {
+ fCurrentEntity.xmlVersion = xmlVersion;
+ } // setXMLVersion(String)
+
+ /** Returns true if the current entity being scanned is external. */
+ public final boolean isExternal() {
+ return fCurrentEntity.isExternal();
+ } // isExternal():boolean
+
+ /**
+ * Returns the next character on the input.
+ *
+ * Note: The character is not consumed.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public int peekChar() throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(peekChar: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // peek at character
+ int c = fCurrentEntity.ch[fCurrentEntity.position];
+
+ // return peeked character
+ if (DEBUG_BUFFER) {
+ System.out.print(")peekChar: ");
+ XMLEntityManager.print(fCurrentEntity);
+ if (fCurrentEntity.isExternal()) {
+ System.out.println(" -> '"+(c!='\r'?(char)c:'\n')+"'");
+ }
+ else {
+ System.out.println(" -> '"+(char)c+"'");
+ }
+ }
+ if (fCurrentEntity.isExternal()) {
+ return c != '\r' ? c : '\n';
+ }
+ else {
+ return c;
+ }
+
+ } // peekChar():int
+
+ /**
+ * Returns the next character on the input.
+ *
+ * Note: The character is consumed.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public int scanChar() throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(scanChar: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // scan character
+ int c = fCurrentEntity.ch[fCurrentEntity.position++];
+ boolean external = false;
+ if (c == '\n' ||
+ (c == '\r' && (external = fCurrentEntity.isExternal()))) {
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = (char)c;
+ load(1, false);
+ }
+ if (c == '\r' && external) {
+ if (fCurrentEntity.ch[fCurrentEntity.position++] != '\n') {
+ fCurrentEntity.position--;
+ }
+ c = '\n';
+ }
+ }
+
+ // return character that was scanned
+ if (DEBUG_BUFFER) {
+ System.out.print(")scanChar: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> '"+(char)c+"'");
+ }
+ fCurrentEntity.columnNumber++;
+ return c;
+
+ } // scanChar():int
+
+ /**
+ * Returns a string matching the NMTOKEN production appearing immediately
+ * on the input as a symbol, or null if NMTOKEN Name string is present.
+ *
+ * Note: The NMTOKEN characters are consumed.
+ *
+ * Note: The string returned must be a symbol. The
+ * SymbolTable can be used for this purpose.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ *
+ * @see org.apache.xerces.util.SymbolTable
+ * @see org.apache.xerces.util.XMLChar#isName
+ */
+ public String scanNmtoken() throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(scanNmtoken: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // scan nmtoken
+ int offset = fCurrentEntity.position;
+ while (XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ offset = 0;
+ if (load(length, false)) {
+ break;
+ }
+ }
+ }
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length;
+
+ // return nmtoken
+ String symbol = null;
+ if (length > 0) {
+ symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
+ }
+ if (DEBUG_BUFFER) {
+ System.out.print(")scanNmtoken: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> "+String.valueOf(symbol));
+ }
+ return symbol;
+
+ } // scanNmtoken():String
+
+ /**
+ * Returns a string matching the Name production appearing immediately
+ * on the input as a symbol, or null if no Name string is present.
+ *
+ * Note: The Name characters are consumed.
+ *
+ * Note: The string returned must be a symbol. The
+ * SymbolTable can be used for this purpose.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ *
+ * @see org.apache.xerces.util.SymbolTable
+ * @see org.apache.xerces.util.XMLChar#isName
+ * @see org.apache.xerces.util.XMLChar#isNameStart
+ */
+ public String scanName() throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(scanName: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // scan name
+ int offset = fCurrentEntity.position;
+ if (XMLChar.isNameStart(fCurrentEntity.ch[offset])) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
+ offset = 0;
+ if (load(1, false)) {
+ fCurrentEntity.columnNumber++;
+ String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
+ if (DEBUG_BUFFER) {
+ System.out.print(")scanName: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> "+String.valueOf(symbol));
+ }
+ return symbol;
+ }
+ }
+ while (XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ offset = 0;
+ if (load(length, false)) {
+ break;
+ }
+ }
+ }
+ }
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length;
+
+ // return name
+ String symbol = null;
+ if (length > 0) {
+ symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
+ }
+ if (DEBUG_BUFFER) {
+ System.out.print(")scanName: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> "+String.valueOf(symbol));
+ }
+ return symbol;
+
+ } // scanName():String
+
+ /**
+ * Returns a string matching the NCName production appearing immediately
+ * on the input as a symbol, or null if no NCName string is present.
+ *
+ * Note: The NCName characters are consumed.
+ *
+ * Note: The string returned must be a symbol. The
+ * SymbolTable can be used for this purpose.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ *
+ * @see org.apache.xerces.util.SymbolTable
+ * @see org.apache.xerces.util.XMLChar#isNCName
+ * @see org.apache.xerces.util.XMLChar#isNCNameStart
+ */
+ public String scanNCName() throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(scanNCName: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // scan name
+ int offset = fCurrentEntity.position;
+ if (XMLChar.isNCNameStart(fCurrentEntity.ch[offset])) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
+ offset = 0;
+ if (load(1, false)) {
+ fCurrentEntity.columnNumber++;
+ String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
+ if (DEBUG_BUFFER) {
+ System.out.print(")scanNCName: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> "+String.valueOf(symbol));
+ }
+ return symbol;
+ }
+ }
+ while (XMLChar.isNCName(fCurrentEntity.ch[fCurrentEntity.position])) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ offset = 0;
+ if (load(length, false)) {
+ break;
+ }
+ }
+ }
+ }
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length;
+
+ // return name
+ String symbol = null;
+ if (length > 0) {
+ symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
+ }
+ if (DEBUG_BUFFER) {
+ System.out.print(")scanNCName: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> "+String.valueOf(symbol));
+ }
+ return symbol;
+
+ } // scanNCName():String
+
+ /**
+ * Scans a qualified name from the input, setting the fields of the
+ * QName structure appropriately.
+ *
+ * Note: The qualified name characters are consumed.
+ *
+ * Note: The strings used to set the values of the
+ * QName structure must be symbols. The SymbolTable can be used for
+ * this purpose.
+ *
+ * @param qname The qualified name structure to fill.
+ *
+ * @return Returns true if a qualified name appeared immediately on
+ * the input and was scanned, false otherwise.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ *
+ * @see org.apache.xerces.util.SymbolTable
+ * @see org.apache.xerces.util.XMLChar#isName
+ * @see org.apache.xerces.util.XMLChar#isNameStart
+ */
+ public boolean scanQName(QName qname) throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(scanQName, "+qname+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // scan qualified name
+ int offset = fCurrentEntity.position;
+ if (XMLChar.isNCNameStart(fCurrentEntity.ch[offset])) {
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
+ offset = 0;
+ if (load(1, false)) {
+ fCurrentEntity.columnNumber++;
+ String name =
+ fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
+ qname.setValues(null, name, name, null);
+ if (DEBUG_BUFFER) {
+ System.out.print(")scanQName, "+qname+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> true");
+ }
+ return true;
+ }
+ }
+ int index = -1;
+ while (XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) {
+ char c = fCurrentEntity.ch[fCurrentEntity.position];
+
+ if (c == ':') {
+ if (index != -1) {
+ break;
+ }
+ index = fCurrentEntity.position;
+ }
+ if (++fCurrentEntity.position == fCurrentEntity.count) {
+ int length = fCurrentEntity.position - offset;
+ if (length == fCurrentEntity.ch.length) {
+ // bad luck we have to resize our buffer
+ resizeBuffer(offset, length);
+ }
+ else {
+ System.arraycopy(fCurrentEntity.ch, offset,
+ fCurrentEntity.ch, 0, length);
+ }
+ if (index != -1) {
+ index = index - offset;
+ }
+ offset = 0;
+ if (load(length, false)) {
+ break;
+ }
+ }
+ }
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length;
+ if (length > 0) {
+ String prefix = null;
+ String localpart = null;
+ String rawname = fSymbolTable.addSymbol(fCurrentEntity.ch,
+ offset, length);
+ if (index != -1) {
+ int prefixLength = index - offset;
+ prefix = fSymbolTable.addSymbol(fCurrentEntity.ch,
+ offset, prefixLength);
+ int len = length - prefixLength - 1;
+ int startLocal = index +1;
+ if (!XMLChar.isNCNameStart(fCurrentEntity.ch[startLocal])){
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "IllegalQName",
+ null,
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ localpart = fSymbolTable.addSymbol(fCurrentEntity.ch,
+ startLocal, len);
+
+ }
+ else {
+ localpart = rawname;
+ }
+ qname.setValues(prefix, localpart, rawname, null);
+ if (DEBUG_BUFFER) {
+ System.out.print(")scanQName, "+qname+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> true");
+ }
+ return true;
+ }
+ }
+
+ // no qualified name found
+ if (DEBUG_BUFFER) {
+ System.out.print(")scanQName, "+qname+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> false");
+ }
+ return false;
+
+ } // scanQName(QName):boolean
+
+ /**
+ * Scans a range of parsed character data, setting the fields of the
+ * XMLString structure, appropriately.
+ *
+ * Note: The characters are consumed.
+ *
+ * Note: This method does not guarantee to return
+ * the longest run of parsed character data. This method may return
+ * before markup due to reaching the end of the input buffer or any
+ * other reason.
+ *
+ * Note: The fields contained in the XMLString
+ * structure are not guaranteed to remain valid upon subsequent calls
+ * to the entity scanner. Therefore, the caller is responsible for
+ * immediately using the returned character data or making a copy of
+ * the character data.
+ *
+ * @param content The content structure to fill.
+ *
+ * @return Returns the next character on the input, if known. This
+ * value may be -1 but this does note designate
+ * end of file.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public int scanContent(XMLString content) throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(scanContent: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+ else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
+ load(1, false);
+ fCurrentEntity.position = 0;
+ fCurrentEntity.startPosition = 0;
+ }
+
+ // normalize newlines
+ int offset = fCurrentEntity.position;
+ int c = fCurrentEntity.ch[offset];
+ int newlines = 0;
+ boolean external = fCurrentEntity.isExternal();
+ if (c == '\n' || (c == '\r' && external)) {
+ if (DEBUG_BUFFER) {
+ System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+ do {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (c == '\r' && external) {
+ newlines++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ offset = 0;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = newlines;
+ fCurrentEntity.startPosition = newlines;
+ if (load(newlines, false)) {
+ break;
+ }
+ }
+ if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
+ fCurrentEntity.position++;
+ offset++;
+ }
+ /*** NEWLINE NORMALIZATION ***/
+ else {
+ newlines++;
+ }
+ }
+ else if (c == '\n') {
+ newlines++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ offset = 0;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = newlines;
+ fCurrentEntity.startPosition = newlines;
+ if (load(newlines, false)) {
+ break;
+ }
+ }
+ }
+ else {
+ fCurrentEntity.position--;
+ break;
+ }
+ } while (fCurrentEntity.position < fCurrentEntity.count - 1);
+ for (int i = offset; i < fCurrentEntity.position; i++) {
+ fCurrentEntity.ch[i] = '\n';
+ }
+ int length = fCurrentEntity.position - offset;
+ if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ content.setValues(fCurrentEntity.ch, offset, length);
+ if (DEBUG_BUFFER) {
+ System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+ return -1;
+ }
+ if (DEBUG_BUFFER) {
+ System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+ }
+
+ // inner loop, scanning for content
+ while (fCurrentEntity.position < fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (!XMLChar.isContent(c)) {
+ fCurrentEntity.position--;
+ break;
+ }
+ }
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length - newlines;
+ content.setValues(fCurrentEntity.ch, offset, length);
+
+ // return next character
+ if (fCurrentEntity.position != fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position];
+ // REVISIT: Does this need to be updated to fix the
+ // #x0D ^#x0A newline normalization problem? -Ac
+ if (c == '\r' && external) {
+ c = '\n';
+ }
+ }
+ else {
+ c = -1;
+ }
+ if (DEBUG_BUFFER) {
+ System.out.print(")scanContent: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> '"+(char)c+"'");
+ }
+ return c;
+
+ } // scanContent(XMLString):int
+
+ /**
+ * Scans a range of attribute value data, setting the fields of the
+ * XMLString structure, appropriately.
+ *
+ * Note: The characters are consumed.
+ *
+ * Note: This method does not guarantee to return
+ * the longest run of attribute value data. This method may return
+ * before the quote character due to reaching the end of the input
+ * buffer or any other reason.
+ *
+ * Note: The fields contained in the XMLString
+ * structure are not guaranteed to remain valid upon subsequent calls
+ * to the entity scanner. Therefore, the caller is responsible for
+ * immediately using the returned character data or making a copy of
+ * the character data.
+ *
+ * @param quote The quote character that signifies the end of the
+ * attribute value data.
+ * @param content The content structure to fill.
+ *
+ * @return Returns the next character on the input, if known. This
+ * value may be -1 but this does note designate
+ * end of file.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public int scanLiteral(int quote, XMLString content)
+ throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(scanLiteral, '"+(char)quote+"': ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+ else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
+ load(1, false);
+ fCurrentEntity.position = 0;
+ fCurrentEntity.startPosition = 0;
+ }
+
+ // normalize newlines
+ int offset = fCurrentEntity.position;
+ int c = fCurrentEntity.ch[offset];
+ int newlines = 0;
+ boolean external = fCurrentEntity.isExternal();
+ if (c == '\n' || (c == '\r' && external)) {
+ if (DEBUG_BUFFER) {
+ System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+ do {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (c == '\r' && external) {
+ newlines++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ offset = 0;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = newlines;
+ fCurrentEntity.startPosition = newlines;
+ if (load(newlines, false)) {
+ break;
+ }
+ }
+ if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
+ fCurrentEntity.position++;
+ offset++;
+ }
+ /*** NEWLINE NORMALIZATION ***/
+ else {
+ newlines++;
+ }
+ /***/
+ }
+ else if (c == '\n') {
+ newlines++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ offset = 0;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = newlines;
+ fCurrentEntity.startPosition = newlines;
+ if (load(newlines, false)) {
+ break;
+ }
+ }
+ }
+ else {
+ fCurrentEntity.position--;
+ break;
+ }
+ } while (fCurrentEntity.position < fCurrentEntity.count - 1);
+ for (int i = offset; i < fCurrentEntity.position; i++) {
+ fCurrentEntity.ch[i] = '\n';
+ }
+ int length = fCurrentEntity.position - offset;
+ if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ content.setValues(fCurrentEntity.ch, offset, length);
+ if (DEBUG_BUFFER) {
+ System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+ return -1;
+ }
+ if (DEBUG_BUFFER) {
+ System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+ }
+
+ // scan literal value
+ while (fCurrentEntity.position < fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if ((c == quote &&
+ (!fCurrentEntity.literal || external))
+ || c == '%' || !XMLChar.isContent(c)) {
+ fCurrentEntity.position--;
+ break;
+ }
+ }
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length - newlines;
+ content.setValues(fCurrentEntity.ch, offset, length);
+
+ // return next character
+ if (fCurrentEntity.position != fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position];
+ // NOTE: We don't want to accidentally signal the
+ // end of the literal if we're expanding an
+ // entity appearing in the literal. -Ac
+ if (c == quote && fCurrentEntity.literal) {
+ c = -1;
+ }
+ }
+ else {
+ c = -1;
+ }
+ if (DEBUG_BUFFER) {
+ System.out.print(")scanLiteral, '"+(char)quote+"': ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> '"+(char)c+"'");
+ }
+ return c;
+
+ } // scanLiteral(int,XMLString):int
+
+ /**
+ * Scans a range of character data up to the specified delimiter,
+ * setting the fields of the XMLString structure, appropriately.
+ *
+ * Note: The characters are consumed.
+ *
+ * Note: This assumes that the internal buffer is
+ * at least the same size, or bigger, than the length of the delimiter
+ * and that the delimiter contains at least one character.
+ *
+ * Note: This method does not guarantee to return
+ * the longest run of character data. This method may return before
+ * the delimiter due to reaching the end of the input buffer or any
+ * other reason.
+ *
+ * Note: The fields contained in the XMLString
+ * structure are not guaranteed to remain valid upon subsequent calls
+ * to the entity scanner. Therefore, the caller is responsible for
+ * immediately using the returned character data or making a copy of
+ * the character data.
+ *
+ * @param delimiter The string that signifies the end of the character
+ * data to be scanned.
+ * @param buffer The XMLStringBuffer to fill.
+ *
+ * @return Returns true if there is more data to scan, false otherwise.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public boolean scanData(String delimiter, XMLStringBuffer buffer)
+ throws IOException {
+
+ // REVISIT: This method does not need to use a string buffer.
+ // The change would avoid the array copies and increase
+ // performance. -Ac
+ //
+ // Currently, this method is called for scanning CDATA
+ // sections, comments, and processing instruction data.
+ // So if this code is updated to NOT buffer, the scanning
+ // code for comments and processing instructions will
+ // need to be updated to do its own buffering. The code
+ // for CDATA sections is safe as-is. -Ac
+
+ boolean found = false;
+ int delimLen = delimiter.length();
+ char charAt0 = delimiter.charAt(0);
+ boolean external = fCurrentEntity.isExternal();
+ if (DEBUG_BUFFER) {
+ System.out.print("(scanData: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ boolean bNextEntity = false;
+
+ while ((fCurrentEntity.position > fCurrentEntity.count - delimLen)
+ && (!bNextEntity))
+ {
+ System.arraycopy(fCurrentEntity.ch,
+ fCurrentEntity.position,
+ fCurrentEntity.ch,
+ 0,
+ fCurrentEntity.count - fCurrentEntity.position);
+
+ bNextEntity = load(fCurrentEntity.count - fCurrentEntity.position, false);
+ fCurrentEntity.position = 0;
+ fCurrentEntity.startPosition = 0;
+ }
+
+ if (fCurrentEntity.position > fCurrentEntity.count - delimLen) {
+ // something must be wrong with the input: e.g., file ends in an unterminated comment
+ int length = fCurrentEntity.count - fCurrentEntity.position;
+ buffer.append (fCurrentEntity.ch, fCurrentEntity.position, length);
+ fCurrentEntity.columnNumber += fCurrentEntity.count;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = fCurrentEntity.count;
+ fCurrentEntity.startPosition = fCurrentEntity.count;
+ load(0,true);
+ return false;
+ }
+
+ // normalize newlines
+ int offset = fCurrentEntity.position;
+ int c = fCurrentEntity.ch[offset];
+ int newlines = 0;
+ if (c == '\n' || (c == '\r' && external)) {
+ if (DEBUG_BUFFER) {
+ System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+ do {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (c == '\r' && external) {
+ newlines++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ offset = 0;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = newlines;
+ fCurrentEntity.startPosition = newlines;
+ if (load(newlines, false)) {
+ break;
+ }
+ }
+ if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
+ fCurrentEntity.position++;
+ offset++;
+ }
+ /*** NEWLINE NORMALIZATION ***/
+ else {
+ newlines++;
+ }
+ }
+ else if (c == '\n') {
+ newlines++;
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ offset = 0;
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ fCurrentEntity.position = newlines;
+ fCurrentEntity.startPosition = newlines;
+ fCurrentEntity.count = newlines;
+ if (load(newlines, false)) {
+ break;
+ }
+ }
+ }
+ else {
+ fCurrentEntity.position--;
+ break;
+ }
+ } while (fCurrentEntity.position < fCurrentEntity.count - 1);
+ for (int i = offset; i < fCurrentEntity.position; i++) {
+ fCurrentEntity.ch[i] = '\n';
+ }
+ int length = fCurrentEntity.position - offset;
+ if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ buffer.append(fCurrentEntity.ch, offset, length);
+ if (DEBUG_BUFFER) {
+ System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+ return true;
+ }
+ if (DEBUG_BUFFER) {
+ System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+ }
+
+ // iterate over buffer looking for delimiter
+ OUTER: while (fCurrentEntity.position < fCurrentEntity.count) {
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (c == charAt0) {
+ // looks like we just hit the delimiter
+ int delimOffset = fCurrentEntity.position - 1;
+ for (int i = 1; i < delimLen; i++) {
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.position -= i;
+ break OUTER;
+ }
+ c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (delimiter.charAt(i) != c) {
+ fCurrentEntity.position--;
+ break;
+ }
+ }
+ if (fCurrentEntity.position == delimOffset + delimLen) {
+ found = true;
+ break;
+ }
+ }
+ else if (c == '\n' || (external && c == '\r')) {
+ fCurrentEntity.position--;
+ break;
+ }
+ else if (XMLChar.isInvalid(c)) {
+ fCurrentEntity.position--;
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length - newlines;
+ buffer.append(fCurrentEntity.ch, offset, length);
+ return true;
+ }
+ }
+ int length = fCurrentEntity.position - offset;
+ fCurrentEntity.columnNumber += length - newlines;
+ if (found) {
+ length -= delimLen;
+ }
+ buffer.append (fCurrentEntity.ch, offset, length);
+
+ // return true if string was skipped
+ if (DEBUG_BUFFER) {
+ System.out.print(")scanData: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> " + !found);
+ }
+ return !found;
+
+ } // scanData(String,XMLString):boolean
+
+ /**
+ * Skips a character appearing immediately on the input.
+ *
+ * Note: The character is consumed only if it matches
+ * the specified character.
+ *
+ * @param c The character to skip.
+ *
+ * @return Returns true if the character was skipped.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public boolean skipChar(int c) throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(skipChar, '"+(char)c+"': ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // skip character
+ int cc = fCurrentEntity.ch[fCurrentEntity.position];
+ if (cc == c) {
+ fCurrentEntity.position++;
+ if (c == '\n') {
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ }
+ else {
+ fCurrentEntity.columnNumber++;
+ }
+ if (DEBUG_BUFFER) {
+ System.out.print(")skipChar, '"+(char)c+"': ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> true");
+ }
+ return true;
+ }
+ else if (c == '\n' && cc == '\r' && fCurrentEntity.isExternal()) {
+ // handle newlines
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ fCurrentEntity.ch[0] = (char)cc;
+ load(1, false);
+ }
+ fCurrentEntity.position++;
+ if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
+ fCurrentEntity.position++;
+ }
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (DEBUG_BUFFER) {
+ System.out.print(")skipChar, '"+(char)c+"': ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> true");
+ }
+ return true;
+ }
+
+ // character was not skipped
+ if (DEBUG_BUFFER) {
+ System.out.print(")skipChar, '"+(char)c+"': ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> false");
+ }
+ return false;
+
+ } // skipChar(int):boolean
+
+ /**
+ * Skips space characters appearing immediately on the input.
+ *
+ * Note: The characters are consumed only if they are
+ * space characters.
+ *
+ * @return Returns true if at least one space character was skipped.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ *
+ * @see org.apache.xerces.util.XMLChar#isSpace
+ */
+ public boolean skipSpaces() throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(skipSpaces: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // skip spaces
+ int c = fCurrentEntity.ch[fCurrentEntity.position];
+ if (XMLChar.isSpace(c)) {
+ boolean external = fCurrentEntity.isExternal();
+ do {
+ boolean entityChanged = false;
+ // handle newlines
+ if (c == '\n' || (external && c == '\r')) {
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ fCurrentEntity.ch[0] = (char)c;
+ entityChanged = load(1, true);
+ if (!entityChanged) {
+ // the load change the position to be 1,
+ // need to restore it when entity not changed
+ fCurrentEntity.position = 0;
+ fCurrentEntity.startPosition = 0;
+ }
+ }
+ if (c == '\r' && external) {
+ // REVISIT: Does this need to be updated to fix the
+ // #x0D ^#x0A newline normalization problem? -Ac
+ if (fCurrentEntity.ch[++fCurrentEntity.position] != '\n') {
+ fCurrentEntity.position--;
+ }
+ }
+ /*** NEWLINE NORMALIZATION ***
+ else {
+ if (fCurrentEntity.ch[fCurrentEntity.position + 1] == '\r'
+ && external) {
+ fCurrentEntity.position++;
+ }
+ }
+ /***/
+ }
+ else {
+ fCurrentEntity.columnNumber++;
+ }
+ // load more characters, if needed
+ if (!entityChanged)
+ fCurrentEntity.position++;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+ } while (XMLChar.isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
+ if (DEBUG_BUFFER) {
+ System.out.print(")skipSpaces: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> true");
+ }
+ return true;
+ }
+
+ // no spaces were found
+ if (DEBUG_BUFFER) {
+ System.out.print(")skipSpaces: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> false");
+ }
+ return false;
+
+ } // skipSpaces():boolean
+
+ /**
+ * Skips space characters appearing immediately on the input that would
+ * match non-terminal S (0x09, 0x0A, 0x0D, 0x20) before end of line
+ * normalization is performed. This is useful when scanning structures
+ * such as the XMLDecl and TextDecl that can only contain US-ASCII
+ * characters.
+ *
+ * Note: The characters are consumed only if they would
+ * match non-terminal S before end of line normalization is performed.
+ *
+ * @return Returns true if at least one space character was skipped.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ *
+ * @see org.apache.xerces.util.XMLChar#isSpace
+ */
+ public final boolean skipDeclSpaces() throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(skipDeclSpaces: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // skip spaces
+ int c = fCurrentEntity.ch[fCurrentEntity.position];
+ if (XMLChar.isSpace(c)) {
+ boolean external = fCurrentEntity.isExternal();
+ do {
+ boolean entityChanged = false;
+ // handle newlines
+ if (c == '\n' || (external && c == '\r')) {
+ fCurrentEntity.lineNumber++;
+ fCurrentEntity.columnNumber = 1;
+ if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ fCurrentEntity.ch[0] = (char)c;
+ entityChanged = load(1, true);
+ if (!entityChanged) {
+ // the load change the position to be 1,
+ // need to restore it when entity not changed
+ fCurrentEntity.position = 0;
+ fCurrentEntity.startPosition = 0;
+ }
+ }
+ if (c == '\r' && external) {
+ // REVISIT: Does this need to be updated to fix the
+ // #x0D ^#x0A newline normalization problem? -Ac
+ if (fCurrentEntity.ch[++fCurrentEntity.position] != '\n') {
+ fCurrentEntity.position--;
+ }
+ }
+ /*** NEWLINE NORMALIZATION ***
+ else {
+ if (fCurrentEntity.ch[fCurrentEntity.position + 1] == '\r'
+ && external) {
+ fCurrentEntity.position++;
+ }
+ }
+ /***/
+ }
+ else {
+ fCurrentEntity.columnNumber++;
+ }
+ // load more characters, if needed
+ if (!entityChanged)
+ fCurrentEntity.position++;
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+ } while (XMLChar.isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
+ if (DEBUG_BUFFER) {
+ System.out.print(")skipDeclSpaces: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> true");
+ }
+ return true;
+ }
+
+ // no spaces were found
+ if (DEBUG_BUFFER) {
+ System.out.print(")skipDeclSpaces: ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> false");
+ }
+ return false;
+
+ } // skipDeclSpaces():boolean
+
+ /**
+ * Skips the specified string appearing immediately on the input.
+ *
+ * Note: The characters are consumed only if they are
+ * space characters.
+ *
+ * @param s The string to skip.
+ *
+ * @return Returns true if the string was skipped.
+ *
+ * @throws IOException Thrown if i/o error occurs.
+ * @throws EOFException Thrown on end of file.
+ */
+ public boolean skipString(String s) throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(skipString, \""+s+"\": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ // load more characters, if needed
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+
+ // skip string
+ final int length = s.length();
+ for (int i = 0; i < length; i++) {
+ char c = fCurrentEntity.ch[fCurrentEntity.position++];
+ if (c != s.charAt(i)) {
+ fCurrentEntity.position -= i + 1;
+ if (DEBUG_BUFFER) {
+ System.out.print(")skipString, \""+s+"\": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> false");
+ }
+ return false;
+ }
+ if (i < length - 1 && fCurrentEntity.position == fCurrentEntity.count) {
+ System.arraycopy(fCurrentEntity.ch, fCurrentEntity.count - i - 1, fCurrentEntity.ch, 0, i + 1);
+ // REVISIT: Can a string to be skipped cross an
+ // entity boundary? -Ac
+ if (load(i + 1, false)) {
+ fCurrentEntity.startPosition -= i + 1;
+ fCurrentEntity.position -= i + 1;
+ if (DEBUG_BUFFER) {
+ System.out.print(")skipString, \""+s+"\": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> false");
+ }
+ return false;
+ }
+ }
+ }
+ if (DEBUG_BUFFER) {
+ System.out.print(")skipString, \""+s+"\": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println(" -> true");
+ }
+ fCurrentEntity.columnNumber += length;
+ return true;
+
+ } // skipString(String):boolean
+
+ //
+ // Locator methods
+ //
+
+ /**
+ * Return the public identifier for the current document event.
+ *
+ * The return value is the public identifier of the document
+ * entity or of the external parsed entity in which the markup
+ * triggering the event appears.
+ *
+ * @return A string containing the public identifier, or
+ * null if none is available.
+ */
+ public final String getPublicId() {
+ return (fCurrentEntity != null && fCurrentEntity.entityLocation != null) ? fCurrentEntity.entityLocation.getPublicId() : null;
+ } // getPublicId():String
+
+ /**
+ * Return the expanded system identifier for the current document event.
+ *
+ * The return value is the expanded system identifier of the document
+ * entity or of the external parsed entity in which the markup
+ * triggering the event appears.
+ *
+ * If the system identifier is a URL, the parser must resolve it
+ * fully before passing it to the application.
+ *
+ * @return A string containing the expanded system identifier, or null
+ * if none is available.
+ */
+ public final String getExpandedSystemId() {
+ if (fCurrentEntity != null) {
+ if (fCurrentEntity.entityLocation != null &&
+ fCurrentEntity.entityLocation.getExpandedSystemId() != null ) {
+ return fCurrentEntity.entityLocation.getExpandedSystemId();
+ }
+ else {
+ // get the current entity to return something appropriate:
+ return fCurrentEntity.getExpandedSystemId();
+ }
+ }
+ return null;
+ } // getExpandedSystemId():String
+
+ /**
+ * Return the literal system identifier for the current document event.
+ *
+ * The return value is the literal system identifier of the document
+ * entity or of the external parsed entity in which the markup
+ * triggering the event appears.
+ *
+ * @return A string containing the literal system identifier, or null
+ * if none is available.
+ */
+ public final String getLiteralSystemId() {
+ if (fCurrentEntity != null) {
+ if (fCurrentEntity.entityLocation != null &&
+ fCurrentEntity.entityLocation.getLiteralSystemId() != null ) {
+ return fCurrentEntity.entityLocation.getLiteralSystemId();
+ }
+ else {
+ // get the current entity to do it:
+ return fCurrentEntity.getLiteralSystemId();
+ }
+ }
+ return null;
+ } // getLiteralSystemId():String
+
+ /**
+ * Returns the line number where the current document event ends.
+ *
+ * Warning: The return value from the method
+ * is intended only as an approximation for the sake of error
+ * reporting; it is not intended to provide sufficient information
+ * to edit the character content of the original XML document.
+ *
+ * The return value is an approximation of the line number
+ * in the document entity or external parsed entity where the
+ * markup triggering the event appears.
+ *
+ * If possible, the line position of the first character after the
+ * text associated with the document event should be provided.
+ * The first line in the document is line 1.
+ *
+ * @return The line number, or -1 if none is available.
+ */
+ public final int getLineNumber() {
+ if (fCurrentEntity != null) {
+ if (fCurrentEntity.isExternal()) {
+ return fCurrentEntity.lineNumber;
+ }
+ else {
+ // ask the current entity to return something appropriate:
+ return fCurrentEntity.getLineNumber();
+ }
+ }
+
+ return -1;
+
+ } // getLineNumber():int
+
+ /**
+ * Returns the column number where the current document event ends.
+ *
+ * Warning: The return value from the method
+ * is intended only as an approximation for the sake of error
+ * reporting; it is not intended to provide sufficient information
+ * to edit the character content of the original XML document.
+ *
+ * The return value is an approximation of the column number
+ * in the document entity or external parsed entity where the
+ * markup triggering the event appears.
+ *
+ * If possible, the line position of the first character after the
+ * text associated with the document event should be provided.
+ * The first column in each line is column 1.
+ *
+ * @return The column number, or -1 if none is available.
+ */
+ public final int getColumnNumber() {
+ if (fCurrentEntity != null) {
+ if (fCurrentEntity.isExternal()) {
+ return fCurrentEntity.columnNumber;
+ }
+ else {
+ // ask current entity to find appropriate column number
+ return fCurrentEntity.getColumnNumber();
+ }
+ }
+
+ return -1;
+ } // getColumnNumber():int
+
+ /**
+ * Returns the character offset where the current document event ends.
+ *
+ * Warning: The return value from the method
+ * is intended only as an approximation for the sake of error
+ * reporting; it is not intended to provide sufficient information
+ * to edit the character content of the original XML document.
+ *
+ * The return value is an approximation of the character offset
+ * in the document entity or external parsed entity where the
+ * markup triggering the event appears.
+ *
+ * If possible, the character offset of the first character after the
+ * text associated with the document event should be provided.
+ *
+ * @return The character offset, or -1 if none is available.
+ */
+ public final int getCharacterOffset() {
+ if (fCurrentEntity != null) {
+ if (fCurrentEntity.isExternal()) {
+ return fCurrentEntity.baseCharOffset + (fCurrentEntity.position - fCurrentEntity.startPosition);
+ }
+ else {
+ // ask current entity to find appropriate character offset
+ return fCurrentEntity.getCharacterOffset();
+ }
+ }
+
+ return -1;
+ } // getCharacterOffset():int
+
+ /**
+ * Returns the encoding of the current entity.
+ * Note that, for a given entity, this value can only be
+ * considered final once the encoding declaration has been read (or once it
+ * has been determined that there is no such declaration) since, no encoding
+ * having been specified on the XMLInputSource, the parser
+ * will make an initial "guess" which could be in error.
+ */
+ public final String getEncoding() {
+ if (fCurrentEntity != null) {
+ if (fCurrentEntity.isExternal()) {
+ return fCurrentEntity.encoding;
+ }
+ else {
+ // ask current entity to find appropriate encoding
+ return fCurrentEntity.getEncoding();
+ }
+ }
+ return null;
+ } // getEncoding():String
+
+ /**
+ * Returns the XML version of the current entity. This will normally be the
+ * value from the XML or text declaration or defaulted by the parser. Note that
+ * that this value may be different than the version of the processing rules
+ * applied to the current entity. For instance, an XML 1.1 document may refer to
+ * XML 1.0 entities. In such a case the rules of XML 1.1 are applied to the entire
+ * document. Also note that, for a given entity, this value can only be considered
+ * final once the XML or text declaration has been read or once it has been
+ * determined that there is no such declaration.
+ */
+ public final String getXMLVersion() {
+ if (fCurrentEntity != null) {
+ if (fCurrentEntity.isExternal()) {
+ return fCurrentEntity.xmlVersion;
+ }
+ else {
+ // ask current entity to find the appropriate XML version
+ return fCurrentEntity.getXMLVersion();
+ }
+ }
+ return null;
+ } // getXMLVersion():String
+
+ // allow entity manager to tell us what the current entityis:
+ public final void setCurrentEntity(XMLEntityManager.ScannedEntity ent) {
+ fCurrentEntity = ent;
+ }
+
+ // set buffer size:
+ public final void setBufferSize(int size) {
+ // REVISIT: Buffer size passed to entity scanner
+ // was not being kept in synch with the actual size
+ // of the buffers in each scanned entity. If any
+ // of the buffers were actually resized, it was possible
+ // that the parser would throw an ArrayIndexOutOfBoundsException
+ // for documents which contained names which are longer than
+ // the current buffer size. Conceivably the buffer size passed
+ // to entity scanner could be used to determine a minimum size
+ // for resizing, if doubling its size is smaller than this
+ // minimum. -- mrglavas
+ fBufferSize = size;
+ }
+
+ // reset what little state we have...
+ public final void reset(SymbolTable symbolTable, XMLEntityManager entityManager,
+ XMLErrorReporter reporter) {
+ fCurrentEntity = null;
+ fSymbolTable = symbolTable;
+ fEntityManager = entityManager;
+ fErrorReporter = reporter;
+ }
+
+ //
+ // Private methods
+ //
+
+ /**
+ * Loads a chunk of text.
+ *
+ * @param offset The offset into the character buffer to
+ * read the next batch of characters.
+ * @param changeEntity True if the load should change entities
+ * at the end of the entity, otherwise leave
+ * the current entity in place and the entity
+ * boundary will be signaled by the return
+ * value.
+ *
+ * @returns Returns true if the entity changed as a result of this
+ * load operation.
+ */
+ final boolean load(int offset, boolean changeEntity)
+ throws IOException {
+ if (DEBUG_BUFFER) {
+ System.out.print("(load, "+offset+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
+ // read characters
+ int length = fCurrentEntity.ch.length - offset;
+ if (!fCurrentEntity.mayReadChunks && length > XMLEntityManager.DEFAULT_XMLDECL_BUFFER_SIZE) {
+ length = XMLEntityManager.DEFAULT_XMLDECL_BUFFER_SIZE;
+ }
+ if (DEBUG_BUFFER) System.out.println(" length to try to read: "+length);
+ int count = fCurrentEntity.reader.read(fCurrentEntity.ch, offset, length);
+ if (DEBUG_BUFFER) System.out.println(" length actually read: "+count);
+
+ // reset count and position
+ boolean entityChanged = false;
+ if (count != -1) {
+ if (count != 0) {
+ fCurrentEntity.count = count + offset;
+ fCurrentEntity.position = offset;
+ fCurrentEntity.startPosition = offset;
+ }
+ }
+
+ // end of this entity
+ else {
+ fCurrentEntity.count = offset;
+ fCurrentEntity.position = offset;
+ fCurrentEntity.startPosition = offset;
+ entityChanged = true;
+ if (changeEntity) {
+ fEntityManager.endEntity();
+ if (fCurrentEntity == null) {
+ throw END_OF_DOCUMENT_ENTITY;
+ }
+ // handle the trailing edges
+ if (fCurrentEntity.position == fCurrentEntity.count) {
+ load(0, true);
+ }
+ }
+ }
+ if (DEBUG_BUFFER) {
+ System.out.print(")load, "+offset+": ");
+ XMLEntityManager.print(fCurrentEntity);
+ System.out.println();
+ }
+
+ return entityChanged;
+
+ } // load(int, boolean):boolean
+
+ /**
+ * This method is invoked to increase the size of the current entity's
+ * buffer if an XML name being scanned is too large to fit within
+ * the buffer at its current size.
+ */
+ final void resizeBuffer(int offset, int length) {
+ char[] tmp = new char[fCurrentEntity.ch.length << 1];
+ System.arraycopy(fCurrentEntity.ch, offset,
+ tmp, 0, length);
+ fCurrentEntity.ch = tmp;
+ } // resizeBuffer(int, int)
+
+} // class XMLEntityScanner
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XMLErrorReporter.java b/resources/xerces2-j-src/org/apache/xerces/impl/XMLErrorReporter.java
new file mode 100644
index 0000000..f23da71
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XMLErrorReporter.java
@@ -0,0 +1,615 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.util.Hashtable;
+import java.util.Locale;
+
+import org.apache.xerces.util.DefaultErrorHandler;
+import org.apache.xerces.util.ErrorHandlerProxy;
+import org.apache.xerces.util.MessageFormatter;
+import org.apache.xerces.xni.XMLLocator;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLComponent;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLErrorHandler;
+import org.apache.xerces.xni.parser.XMLParseException;
+import org.xml.sax.ErrorHandler;
+
+/**
+ * This class is a common element of all parser configurations and is
+ * used to report errors that occur. This component can be queried by
+ * parser components from the component manager using the following
+ * property ID:
+ *
+ * http://apache.org/xml/properties/internal/error-reporter
+ *
+ *
+ * Errors are separated into domains that categorize a class of errors.
+ * In a parser configuration, the parser would register a
+ * MessageFormatter for each domain that is capable of
+ * localizing error messages and formatting them based on information
+ * about the error. Any parser component can invent new error domains
+ * and register additional message formatters to localize messages in
+ * those domains.
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://apache.org/xml/properties/internal/error-handler
+ *
+ *
+ * This component can use the following features and properties but they
+ * are not required:
+ *
+ * - http://apache.org/xml/features/continue-after-fatal-error
+ *
+ *
+ * @xerces.internal
+ *
+ * @see MessageFormatter
+ *
+ * @author Eric Ye, IBM
+ * @author Andy Clark, IBM
+ *
+ * @version $Id$
+ */
+public class XMLErrorReporter
+ implements XMLComponent {
+
+ //
+ // Constants
+ //
+
+ // severity
+
+ /**
+ * Severity: warning. Warnings represent informational messages only
+ * that should not be considered serious enough to stop parsing or
+ * indicate an error in the document's validity.
+ */
+ public static final short SEVERITY_WARNING = 0;
+
+ /**
+ * Severity: error. Common causes of errors are document structure and/or
+ * content that that does not conform to the grammar rules specified for
+ * the document. These are typically validation errors.
+ */
+ public static final short SEVERITY_ERROR = 1;
+
+ /**
+ * Severity: fatal error. Fatal errors are errors in the syntax of the
+ * XML document or invalid byte sequences for a given encoding. The
+ * XML 1.0 Specification mandates that errors of this type are not
+ * recoverable.
+ *
+ * Note: The parser does have a "continue after fatal
+ * error" feature but it should be used with extreme caution and care.
+ */
+ public static final short SEVERITY_FATAL_ERROR = 2;
+
+ // feature identifiers
+
+ /** Feature identifier: continue after fatal error. */
+ protected static final String CONTINUE_AFTER_FATAL_ERROR =
+ Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
+
+ // property identifiers
+
+ /** Property identifier: error handler. */
+ protected static final String ERROR_HANDLER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
+
+ // recognized features and properties
+
+ /** Recognized features. */
+ private static final String[] RECOGNIZED_FEATURES = {
+ CONTINUE_AFTER_FATAL_ERROR,
+ };
+
+ /** Feature defaults. */
+ private static final Boolean[] FEATURE_DEFAULTS = {
+ null,
+ };
+
+ /** Recognized properties. */
+ private static final String[] RECOGNIZED_PROPERTIES = {
+ ERROR_HANDLER,
+ };
+
+ /** Property defaults. */
+ private static final Object[] PROPERTY_DEFAULTS = {
+ null,
+ };
+
+ //
+ // Data
+ //
+
+ /** The locale to be used to format error messages. */
+ protected Locale fLocale;
+
+ /** Mapping of Message formatters for domains. */
+ protected Hashtable fMessageFormatters;
+
+ /** Error handler. */
+ protected XMLErrorHandler fErrorHandler;
+
+ /** Document locator. */
+ protected XMLLocator fLocator;
+
+ /** Continue after fatal error feature. */
+ protected boolean fContinueAfterFatalError;
+
+ /**
+ * Default error handler. This error handler is only used in the
+ * absence of a registered error handler so that errors are not
+ * "swallowed" silently. This is one of the most common "problems"
+ * reported by users of the parser.
+ */
+ protected XMLErrorHandler fDefaultErrorHandler;
+
+ /** A SAX proxy to the error handler contained in this error reporter. */
+ private ErrorHandler fSaxProxy = null;
+
+ //
+ // Constructors
+ //
+
+ /** Constructs an error reporter with a locator. */
+ public XMLErrorReporter() {
+
+ // REVISIT: [Q] Should the locator be passed to the reportError
+ // method? Otherwise, there is no way for a parser
+ // component to store information about where an
+ // error occurred so as to report it later.
+ //
+ // An example would be to record the location of
+ // IDREFs so that, at the end of the document, if
+ // there is no associated ID declared, the error
+ // could report the location information of the
+ // reference. -Ac
+ //
+ // NOTE: I added another reportError method that allows the
+ // caller to specify the location of the error being
+ // reported. -Ac
+
+ fMessageFormatters = new Hashtable();
+
+ } // ()
+
+ //
+ // Methods
+ //
+
+ /**
+ * Sets the current locale.
+ *
+ * @param locale The new locale.
+ */
+ public void setLocale(Locale locale) {
+ fLocale = locale;
+ } // setLocale(Locale)
+
+ /**
+ * Gets the current locale.
+ *
+ * @return the current Locale
+ */
+ public Locale getLocale() {
+ return fLocale ;
+ } // getLocale(): Locale
+
+ /**
+ * Sets the document locator.
+ *
+ * @param locator The locator.
+ */
+ public void setDocumentLocator(XMLLocator locator) {
+ fLocator = locator;
+ } // setDocumentLocator(XMLLocator)
+
+ /**
+ * Registers a message formatter for the specified domain.
+ *
+ * Note: Registering a message formatter for a domain
+ * when there is already a formatter registered will cause the previous
+ * formatter to be lost. This method replaces any previously registered
+ * message formatter for the specified domain.
+ *
+ * @param domain
+ * @param messageFormatter
+ */
+ public void putMessageFormatter(String domain,
+ MessageFormatter messageFormatter) {
+ fMessageFormatters.put(domain, messageFormatter);
+ } // putMessageFormatter(String,MessageFormatter)
+
+ /**
+ * Returns the message formatter associated with the specified domain,
+ * or null if no message formatter is registered for that domain.
+ *
+ * @param domain The domain of the message formatter.
+ */
+ public MessageFormatter getMessageFormatter(String domain) {
+ return (MessageFormatter)fMessageFormatters.get(domain);
+ } // getMessageFormatter(String):MessageFormatter
+
+ /**
+ * Removes the message formatter for the specified domain and
+ * returns the removed message formatter.
+ *
+ * @param domain The domain of the message formatter.
+ */
+ public MessageFormatter removeMessageFormatter(String domain) {
+ return (MessageFormatter) fMessageFormatters.remove(domain);
+ } // removeMessageFormatter(String):MessageFormatter
+
+ /**
+ * Reports an error. The error message passed to the error handler
+ * is formatted for the locale by the message formatter installed
+ * for the specified error domain.
+ *
+ * @param domain The error domain.
+ * @param key The key of the error message.
+ * @param arguments The replacement arguments for the error message,
+ * if needed.
+ * @param severity The severity of the error.
+ * @return The formatted error message.
+ *
+ * @see #SEVERITY_WARNING
+ * @see #SEVERITY_ERROR
+ * @see #SEVERITY_FATAL_ERROR
+ */
+ public String reportError(String domain, String key, Object[] arguments,
+ short severity) throws XNIException {
+ return reportError(fLocator, domain, key, arguments, severity);
+ } // reportError(String,String,Object[],short):String
+
+ /**
+ * Reports an error. The error message passed to the error handler
+ * is formatted for the locale by the message formatter installed
+ * for the specified error domain.
+ *
+ * @param domain The error domain.
+ * @param key The key of the error message.
+ * @param arguments The replacement arguments for the error message,
+ * if needed.
+ * @param severity The severity of the error.
+ * @param exception The exception to wrap.
+ * @return The formatted error message.
+ *
+ * @see #SEVERITY_WARNING
+ * @see #SEVERITY_ERROR
+ * @see #SEVERITY_FATAL_ERROR
+ */
+ public String reportError(String domain, String key, Object[] arguments,
+ short severity, Exception exception) throws XNIException {
+ return reportError(fLocator, domain, key, arguments, severity, exception);
+ } // reportError(String,String,Object[],short,Exception):String
+
+ /**
+ * Reports an error at a specific location.
+ *
+ * @param location The error location.
+ * @param domain The error domain.
+ * @param key The key of the error message.
+ * @param arguments The replacement arguments for the error message,
+ * if needed.
+ * @param severity The severity of the error.
+ * @return The formatted error message.
+ *
+ * @see #SEVERITY_WARNING
+ * @see #SEVERITY_ERROR
+ * @see #SEVERITY_FATAL_ERROR
+ */
+ public String reportError(XMLLocator location,
+ String domain, String key, Object[] arguments,
+ short severity) throws XNIException {
+ return reportError(location, domain, key, arguments, severity, null);
+ } // reportError(XMLLocator,String,String,Object[],short):String
+
+ /**
+ * Reports an error at a specific location.
+ *
+ * @param location The error location.
+ * @param domain The error domain.
+ * @param key The key of the error message.
+ * @param arguments The replacement arguments for the error message,
+ * if needed.
+ * @param severity The severity of the error.
+ * @param exception The exception to wrap.
+ * @return The formatted error message.
+ *
+ * @see #SEVERITY_WARNING
+ * @see #SEVERITY_ERROR
+ * @see #SEVERITY_FATAL_ERROR
+ */
+ public String reportError(XMLLocator location,
+ String domain, String key, Object[] arguments,
+ short severity, Exception exception) throws XNIException {
+
+ // REVISIT: [Q] Should we do anything about invalid severity
+ // parameter? -Ac
+
+ // format error message and create parse exception
+ MessageFormatter messageFormatter = getMessageFormatter(domain);
+ String message;
+ if (messageFormatter != null) {
+ message = messageFormatter.formatMessage(fLocale, key, arguments);
+ }
+ else {
+ StringBuffer str = new StringBuffer();
+ str.append(domain);
+ str.append('#');
+ str.append(key);
+ int argCount = arguments != null ? arguments.length : 0;
+ if (argCount > 0) {
+ str.append('?');
+ for (int i = 0; i < argCount; i++) {
+ str.append(arguments[i]);
+ if (i < argCount -1) {
+ str.append('&');
+ }
+ }
+ }
+ message = str.toString();
+ }
+ XMLParseException parseException = (exception != null) ?
+ new XMLParseException(location, message, exception) :
+ new XMLParseException(location, message);
+
+ // get error handler
+ XMLErrorHandler errorHandler = fErrorHandler;
+ if (errorHandler == null) {
+ if (fDefaultErrorHandler == null) {
+ fDefaultErrorHandler = new DefaultErrorHandler();
+ }
+ errorHandler = fDefaultErrorHandler;
+ }
+
+ // call error handler
+ switch (severity) {
+ case SEVERITY_WARNING: {
+ errorHandler.warning(domain, key, parseException);
+ break;
+ }
+ case SEVERITY_ERROR: {
+ errorHandler.error(domain, key, parseException);
+ break;
+ }
+ case SEVERITY_FATAL_ERROR: {
+ errorHandler.fatalError(domain, key, parseException);
+ if (!fContinueAfterFatalError) {
+ throw parseException;
+ }
+ break;
+ }
+ }
+ return message;
+
+ } // reportError(XMLLocator,String,String,Object[],short,Exception):String
+
+ //
+ // XMLComponent methods
+ //
+
+ /**
+ * Resets the component. The component can query the component manager
+ * about any features and properties that affect the operation of the
+ * component.
+ *
+ * @param componentManager The component manager.
+ *
+ * @throws SAXException Thrown by component on initialization error.
+ * For example, if a feature or property is
+ * required for the operation of the component, the
+ * component manager may throw a
+ * SAXNotRecognizedException or a
+ * SAXNotSupportedException.
+ */
+ public void reset(XMLComponentManager componentManager)
+ throws XNIException {
+
+ // features
+ try {
+ fContinueAfterFatalError = componentManager.getFeature(CONTINUE_AFTER_FATAL_ERROR);
+ }
+ catch (XNIException e) {
+ fContinueAfterFatalError = false;
+ }
+
+ // properties
+ fErrorHandler = (XMLErrorHandler)componentManager.getProperty(ERROR_HANDLER);
+
+ } // reset(XMLComponentManager)
+
+ /**
+ * Returns a list of feature identifiers that are recognized by
+ * this component. This method may return null if no features
+ * are recognized by this component.
+ */
+ public String[] getRecognizedFeatures() {
+ return (String[])(RECOGNIZED_FEATURES.clone());
+ } // getRecognizedFeatures():String[]
+
+ /**
+ * Sets the state of a feature. This method is called by the component
+ * manager any time after reset when a feature changes state.
+ *
+ * Note: Components should silently ignore features
+ * that do not affect the operation of the component.
+ *
+ * @param featureId The feature identifier.
+ * @param state The state of the feature.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setFeature(String featureId, boolean state)
+ throws XMLConfigurationException {
+
+ //
+ // Xerces features
+ //
+
+ if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
+ final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
+
+ //
+ // http://apache.org/xml/features/continue-after-fatal-error
+ // Allows the parser to continue after a fatal error.
+ // Normally, a fatal error would stop the parse.
+ //
+ if (suffixLength == Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE.length() &&
+ featureId.endsWith(Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE)) {
+ fContinueAfterFatalError = state;
+ }
+ }
+
+ } // setFeature(String,boolean)
+
+ // return state of given feature or false if unsupported.
+ public boolean getFeature(String featureId)
+ throws XMLConfigurationException {
+
+ //
+ // Xerces features
+ //
+
+ if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
+ final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
+
+ //
+ // http://apache.org/xml/features/continue-after-fatal-error
+ // Allows the parser to continue after a fatal error.
+ // Normally, a fatal error would stop the parse.
+ //
+ if (suffixLength == Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE.length() &&
+ featureId.endsWith(Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE)) {
+ return fContinueAfterFatalError ;
+ }
+ }
+ return false;
+
+ } // setFeature(String,boolean)
+
+ /**
+ * Returns a list of property identifiers that are recognized by
+ * this component. This method may return null if no properties
+ * are recognized by this component.
+ */
+ public String[] getRecognizedProperties() {
+ return (String[])(RECOGNIZED_PROPERTIES.clone());
+ } // getRecognizedProperties():String[]
+
+ /**
+ * Sets the value of a property. This method is called by the component
+ * manager any time after reset when a property changes value.
+ *
+ * Note: Components should silently ignore properties
+ * that do not affect the operation of the component.
+ *
+ * @param propertyId The property identifier.
+ * @param value The value of the property.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setProperty(String propertyId, Object value)
+ throws XMLConfigurationException {
+
+ //
+ // Xerces properties
+ //
+
+ if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
+ final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
+
+ if (suffixLength == Constants.ERROR_HANDLER_PROPERTY.length() &&
+ propertyId.endsWith(Constants.ERROR_HANDLER_PROPERTY)) {
+ fErrorHandler = (XMLErrorHandler)value;
+ }
+ }
+
+ } // setProperty(String,Object)
+
+ /**
+ * Returns the default state for a feature, or null if this
+ * component does not want to report a default value for this
+ * feature.
+ *
+ * @param featureId The feature identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Boolean getFeatureDefault(String featureId) {
+ for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
+ if (RECOGNIZED_FEATURES[i].equals(featureId)) {
+ return FEATURE_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getFeatureDefault(String):Boolean
+
+ /**
+ * Returns the default state for a property, or null if this
+ * component does not want to report a default value for this
+ * property.
+ *
+ * @param propertyId The property identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Object getPropertyDefault(String propertyId) {
+ for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
+ if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
+ return PROPERTY_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getPropertyDefault(String):Object
+
+ /**
+ * Get the internal XMLErrrorHandler.
+ */
+ public XMLErrorHandler getErrorHandler() {
+ return fErrorHandler;
+ }
+
+ /**
+ * Gets the internal XMLErrorHandler
+ * as SAX ErrorHandler.
+ */
+ public ErrorHandler getSAXErrorHandler() {
+ if (fSaxProxy == null) {
+ fSaxProxy = new ErrorHandlerProxy() {
+ protected XMLErrorHandler getErrorHandler() {
+ return fErrorHandler;
+ }
+ };
+ }
+ return fSaxProxy;
+ }
+
+} // class XMLErrorReporter
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XMLNSDocumentScannerImpl.java b/resources/xerces2-j-src/org/apache/xerces/impl/XMLNSDocumentScannerImpl.java
new file mode 100644
index 0000000..8cb0332
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XMLNSDocumentScannerImpl.java
@@ -0,0 +1,768 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.io.IOException;
+
+import org.apache.xerces.impl.dtd.XMLDTDValidatorFilter;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.XMLAttributesImpl;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLDocumentHandler;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLDocumentSource;
+
+/**
+ * The scanner acts as the source for the document
+ * information which is communicated to the document handler.
+ *
+ * This class scans an XML document, checks if document has a DTD, and if
+ * DTD is not found the scanner will remove the DTD Validator from the pipeline and perform
+ * namespace binding.
+ *
+ * Note: This scanner should only be used when the namespace processing is on!
+ *
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/namespaces {true} -- if the value of this
+ * feature is set to false this scanner must not be used.
+ * - http://xml.org/sax/features/validation
+ * - http://apache.org/xml/features/nonvalidating/load-external-dtd
+ * - http://apache.org/xml/features/scanner/notify-char-refs
+ * - http://apache.org/xml/features/scanner/notify-builtin-refs
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/entity-manager
+ * - http://apache.org/xml/properties/internal/dtd-scanner
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani, IBM
+ *
+ * @version $Id$
+ */
+public class XMLNSDocumentScannerImpl
+extends XMLDocumentScannerImpl {
+
+ /** If is true, the dtd validator is no longer in the pipeline
+ * and the scanner should bind namespaces */
+ protected boolean fBindNamespaces;
+
+ /** If validating parser, make sure we report an error in the
+ * scanner if DTD grammar is missing.*/
+ protected boolean fPerformValidation;
+
+ // private data
+ //
+
+ /** DTD validator */
+ private XMLDTDValidatorFilter fDTDValidator;
+
+ /**
+ * Saw spaces after element name or between attributes.
+ *
+ * This is reserved for the case where scanning of a start element spans
+ * several methods, as is the case when scanning the start of a root element
+ * where a DTD external subset may be read after scanning the element name.
+ */
+ private boolean fSawSpace;
+
+
+ /**
+ * The scanner is responsible for removing DTD validator
+ * from the pipeline if it is not needed.
+ *
+ * @param dtdValidator The DTDValidator
+ */
+ public void setDTDValidator(XMLDTDValidatorFilter dtdValidator) {
+ fDTDValidator = dtdValidator;
+ }
+
+ /**
+ * Scans a start element. This method will handle the binding of
+ * namespace information and notifying the handler of the start
+ * of the element.
+ *
+ *
+ * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
+ * [40] STag ::= '<' Name (S Attribute)* S? '>'
+ *
+ *
+ * Note: This method assumes that the leading
+ * '<' character has been consumed.
+ *
+ * Note: This method uses the fElementQName and
+ * fAttributes variables. The contents of these variables will be
+ * destroyed. The caller should copy important information out of
+ * these variables before calling this method.
+ *
+ * @return True if element is empty. (i.e. It matches
+ * production [44].
+ */
+ protected boolean scanStartElement()
+ throws IOException, XNIException {
+ if (DEBUG_CONTENT_SCANNING) System.out.println(">>> scanStartElementNS()");
+
+ // Note: namespace processing is on by default
+ fEntityScanner.scanQName(fElementQName);
+ // REVISIT - [Q] Why do we need this temp variable? -- mrglavas
+ String rawname = fElementQName.rawname;
+ if (fBindNamespaces) {
+ fNamespaceContext.pushContext();
+ if (fScannerState == SCANNER_STATE_ROOT_ELEMENT) {
+ if (fPerformValidation) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_GRAMMAR_NOT_FOUND",
+ new Object[]{ rawname},
+ XMLErrorReporter.SEVERITY_ERROR);
+
+ if (fDoctypeName == null || !fDoctypeName.equals(rawname)) {
+ fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
+ "RootElementTypeMustMatchDoctypedecl",
+ new Object[]{fDoctypeName, rawname},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ }
+ }
+
+ // push element stack
+ fCurrentElement = fElementStack.pushElement(fElementQName);
+
+ // attributes
+ boolean empty = false;
+ fAttributes.removeAllAttributes();
+ do {
+ // spaces
+ boolean sawSpace = fEntityScanner.skipSpaces();
+
+ // end tag?
+ int c = fEntityScanner.peekChar();
+ if (c == '>') {
+ fEntityScanner.scanChar();
+ break;
+ }
+ else if (c == '/') {
+ fEntityScanner.scanChar();
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError("ElementUnterminated",
+ new Object[]{rawname});
+ }
+ empty = true;
+ break;
+ }
+ else if (!isValidNameStartChar(c) || !sawSpace) {
+ reportFatalError("ElementUnterminated", new Object[]{rawname});
+ }
+
+ // attributes
+ scanAttribute(fAttributes);
+
+ } while (true);
+
+ if (fBindNamespaces) {
+ // REVISIT: is it required? forbit xmlns prefix for element
+ if (fElementQName.prefix == XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementXMLNSPrefix",
+ new Object[]{fElementQName.rawname},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // bind the element
+ String prefix = fElementQName.prefix != null
+ ? fElementQName.prefix : XMLSymbols.EMPTY_STRING;
+ // assign uri to the element
+ fElementQName.uri = fNamespaceContext.getURI(prefix);
+ // make sure that object in the element stack is updated as well
+ fCurrentElement.uri = fElementQName.uri;
+
+ if (fElementQName.prefix == null && fElementQName.uri != null) {
+ fElementQName.prefix = XMLSymbols.EMPTY_STRING;
+ // making sure that the object in the element stack is updated too.
+ fCurrentElement.prefix = XMLSymbols.EMPTY_STRING;
+ }
+ if (fElementQName.prefix != null && fElementQName.uri == null) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementPrefixUnbound",
+ new Object[]{fElementQName.prefix, fElementQName.rawname},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // bind attributes (xmlns are already bound bellow)
+ int length = fAttributes.getLength();
+ // fLength = 0; //initialize structure
+ for (int i = 0; i < length; i++) {
+ fAttributes.getName(i, fAttributeQName);
+
+ String aprefix = fAttributeQName.prefix != null
+ ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
+ String uri = fNamespaceContext.getURI(aprefix);
+ // REVISIT: try removing the first "if" and see if it is faster.
+ //
+ if (fAttributeQName.uri != null && fAttributeQName.uri == uri) {
+ // checkDuplicates(fAttributeQName, fAttributes);
+ continue;
+ }
+ if (aprefix != XMLSymbols.EMPTY_STRING) {
+ fAttributeQName.uri = uri;
+ if (uri == null) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributePrefixUnbound",
+ new Object[]{fElementQName.rawname,fAttributeQName.rawname,aprefix},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ fAttributes.setURI(i, uri);
+ // checkDuplicates(fAttributeQName, fAttributes);
+ }
+ }
+
+ if (length > 1) {
+ QName name = fAttributes.checkDuplicatesNS();
+ if (name != null) {
+ if (name.uri != null) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNSNotUnique",
+ new Object[]{fElementQName.rawname, name.localpart, name.uri},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ else {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNotUnique",
+ new Object[]{fElementQName.rawname, name.rawname},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ }
+ }
+
+
+ // call handler
+ if (fDocumentHandler != null) {
+ if (empty) {
+
+ //decrease the markup depth..
+ fMarkupDepth--;
+
+ // check that this element was opened in the same entity
+ if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
+ reportFatalError("ElementEntityMismatch",
+ new Object[]{fCurrentElement.rawname});
+ }
+
+ fDocumentHandler.emptyElement(fElementQName, fAttributes, null);
+
+ if (fBindNamespaces) {
+ fNamespaceContext.popContext();
+ }
+ //pop the element off the stack..
+ fElementStack.popElement(fElementQName);
+ } else {
+ fDocumentHandler.startElement(fElementQName, fAttributes, null);
+ }
+ }
+
+ if (DEBUG_CONTENT_SCANNING) System.out.println("<<< scanStartElement(): "+empty);
+ return empty;
+
+ } // scanStartElement():boolean
+
+ /**
+ * Scans the name of an element in a start or empty tag.
+ *
+ * @see #scanStartElement()
+ */
+ protected void scanStartElementName ()
+ throws IOException, XNIException {
+ // Note: namespace processing is on by default
+ fEntityScanner.scanQName(fElementQName);
+ // Must skip spaces here because the DTD scanner
+ // would consume them at the end of the external subset.
+ fSawSpace = fEntityScanner.skipSpaces();
+ } // scanStartElementName()
+
+ /**
+ * Scans the remainder of a start or empty tag after the element name.
+ *
+ * @see #scanStartElement
+ * @return True if element is empty.
+ */
+ protected boolean scanStartElementAfterName()
+ throws IOException, XNIException {
+
+ // REVISIT - [Q] Why do we need this temp variable? -- mrglavas
+ String rawname = fElementQName.rawname;
+ if (fBindNamespaces) {
+ fNamespaceContext.pushContext();
+ if (fScannerState == SCANNER_STATE_ROOT_ELEMENT) {
+ if (fPerformValidation) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_GRAMMAR_NOT_FOUND",
+ new Object[]{ rawname},
+ XMLErrorReporter.SEVERITY_ERROR);
+
+ if (fDoctypeName == null || !fDoctypeName.equals(rawname)) {
+ fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
+ "RootElementTypeMustMatchDoctypedecl",
+ new Object[]{fDoctypeName, rawname},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ }
+ }
+
+ // push element stack
+ fCurrentElement = fElementStack.pushElement(fElementQName);
+
+ // attributes
+ boolean empty = false;
+ fAttributes.removeAllAttributes();
+ do {
+
+ // end tag?
+ int c = fEntityScanner.peekChar();
+ if (c == '>') {
+ fEntityScanner.scanChar();
+ break;
+ }
+ else if (c == '/') {
+ fEntityScanner.scanChar();
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError("ElementUnterminated",
+ new Object[]{rawname});
+ }
+ empty = true;
+ break;
+ }
+ else if (!isValidNameStartChar(c) || !fSawSpace) {
+ reportFatalError("ElementUnterminated", new Object[]{rawname});
+ }
+
+ // attributes
+ scanAttribute(fAttributes);
+
+ // spaces
+ fSawSpace = fEntityScanner.skipSpaces();
+
+ } while (true);
+
+ if (fBindNamespaces) {
+ // REVISIT: is it required? forbit xmlns prefix for element
+ if (fElementQName.prefix == XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementXMLNSPrefix",
+ new Object[]{fElementQName.rawname},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // bind the element
+ String prefix = fElementQName.prefix != null
+ ? fElementQName.prefix : XMLSymbols.EMPTY_STRING;
+ // assign uri to the element
+ fElementQName.uri = fNamespaceContext.getURI(prefix);
+ // make sure that object in the element stack is updated as well
+ fCurrentElement.uri = fElementQName.uri;
+
+ if (fElementQName.prefix == null && fElementQName.uri != null) {
+ fElementQName.prefix = XMLSymbols.EMPTY_STRING;
+ // making sure that the object in the element stack is updated too.
+ fCurrentElement.prefix = XMLSymbols.EMPTY_STRING;
+ }
+ if (fElementQName.prefix != null && fElementQName.uri == null) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementPrefixUnbound",
+ new Object[]{fElementQName.prefix, fElementQName.rawname},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // bind attributes (xmlns are already bound bellow)
+ int length = fAttributes.getLength();
+ // fLength = 0; //initialize structure
+ for (int i = 0; i < length; i++) {
+ fAttributes.getName(i, fAttributeQName);
+
+ String aprefix = fAttributeQName.prefix != null
+ ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
+ String uri = fNamespaceContext.getURI(aprefix);
+ // REVISIT: try removing the first "if" and see if it is faster.
+ //
+ if (fAttributeQName.uri != null && fAttributeQName.uri == uri) {
+ // checkDuplicates(fAttributeQName, fAttributes);
+ continue;
+ }
+ if (aprefix != XMLSymbols.EMPTY_STRING) {
+ fAttributeQName.uri = uri;
+ if (uri == null) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributePrefixUnbound",
+ new Object[]{fElementQName.rawname,fAttributeQName.rawname,aprefix},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ fAttributes.setURI(i, uri);
+ // checkDuplicates(fAttributeQName, fAttributes);
+ }
+ }
+
+ if (length > 1) {
+ QName name = fAttributes.checkDuplicatesNS();
+ if (name != null) {
+ if (name.uri != null) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNSNotUnique",
+ new Object[]{fElementQName.rawname, name.localpart, name.uri},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ else {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNotUnique",
+ new Object[]{fElementQName.rawname, name.rawname},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ }
+ }
+
+
+ // call handler
+ if (fDocumentHandler != null) {
+ if (empty) {
+
+ //decrease the markup depth..
+ fMarkupDepth--;
+
+ // check that this element was opened in the same entity
+ if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
+ reportFatalError("ElementEntityMismatch",
+ new Object[]{fCurrentElement.rawname});
+ }
+
+ fDocumentHandler.emptyElement(fElementQName, fAttributes, null);
+
+ if (fBindNamespaces) {
+ fNamespaceContext.popContext();
+ }
+ //pop the element off the stack..
+ fElementStack.popElement(fElementQName);
+ } else {
+ fDocumentHandler.startElement(fElementQName, fAttributes, null);
+ }
+ }
+
+ if (DEBUG_CONTENT_SCANNING) System.out.println("<<< scanStartElementAfterName(): "+empty);
+ return empty;
+ } // scanStartElementAfterName()
+
+ /**
+ * Scans an attribute.
+ *
+ *
+ * [41] Attribute ::= Name Eq AttValue
+ *
+ *
+ * Note: This method assumes that the next
+ * character on the stream is the first character of the attribute
+ * name.
+ *
+ * Note: This method uses the fAttributeQName and
+ * fQName variables. The contents of these variables will be
+ * destroyed.
+ *
+ * @param attributes The attributes list for the scanned attribute.
+ */
+ protected void scanAttribute(XMLAttributesImpl attributes)
+ throws IOException, XNIException {
+ if (DEBUG_CONTENT_SCANNING) System.out.println(">>> scanAttribute()");
+
+ // name
+ fEntityScanner.scanQName(fAttributeQName);
+
+ // equals
+ fEntityScanner.skipSpaces();
+ if (!fEntityScanner.skipChar('=')) {
+ reportFatalError("EqRequiredInAttribute",
+ new Object[]{fCurrentElement.rawname,fAttributeQName.rawname});
+ }
+ fEntityScanner.skipSpaces();
+
+ // content
+ int attrIndex;
+
+ if (fBindNamespaces) {
+ attrIndex = attributes.getLength();
+ attributes.addAttributeNS(fAttributeQName, XMLSymbols.fCDATASymbol, null);
+ }
+ else {
+ int oldLen = attributes.getLength();
+ attrIndex = attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null);
+
+ // WFC: Unique Att Spec
+ if (oldLen == attributes.getLength()) {
+ reportFatalError("AttributeNotUnique",
+ new Object[]{fCurrentElement.rawname,
+ fAttributeQName.rawname});
+ }
+ }
+
+ // Scan attribute value and return true if the non-normalized and normalized value are the same
+ boolean isSameNormalizedAttr = scanAttributeValue(this.fTempString, fTempString2,
+ fAttributeQName.rawname, fIsEntityDeclaredVC, fCurrentElement.rawname);
+
+ String value = fTempString.toString();
+ attributes.setValue(attrIndex, value);
+ // If the non-normalized and normalized value are the same, avoid creating a new string.
+ if (!isSameNormalizedAttr) {
+ attributes.setNonNormalizedValue(attrIndex, fTempString2.toString());
+ }
+ attributes.setSpecified(attrIndex, true);
+
+ // record namespace declarations if any.
+ if (fBindNamespaces) {
+
+ String localpart = fAttributeQName.localpart;
+ String prefix = fAttributeQName.prefix != null
+ ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
+ // when it's of form xmlns="..." or xmlns:prefix="...",
+ // it's a namespace declaration. but prefix:xmlns="..." isn't.
+ if (prefix == XMLSymbols.PREFIX_XMLNS ||
+ prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) {
+
+ // get the internalized value of this attribute
+ String uri = fSymbolTable.addSymbol(value);
+
+ // 1. "xmlns" can't be bound to any namespace
+ if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXMLNS",
+ new Object[]{fAttributeQName},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // 2. the namespace for "xmlns" can't be bound to any prefix
+ if (uri == NamespaceContext.XMLNS_URI) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXMLNS",
+ new Object[]{fAttributeQName},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // 3. "xml" can't be bound to any other namespace than it's own
+ if (localpart == XMLSymbols.PREFIX_XML) {
+ if (uri != NamespaceContext.XML_URI) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXML",
+ new Object[]{fAttributeQName},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ // 4. the namespace for "xml" can't be bound to any other prefix
+ else {
+ if (uri ==NamespaceContext.XML_URI) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXML",
+ new Object[]{fAttributeQName},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+
+ prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING;
+
+ // http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix
+ // We should only report an error if there is a prefix,
+ // that is, the local part is not "xmlns". -SG
+ if (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "EmptyPrefixedAttName",
+ new Object[]{fAttributeQName},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // declare prefix in context
+ fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null);
+ // bind namespace attribute to a namespace
+ attributes.setURI(attrIndex, fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS));
+
+ }
+ else {
+ // attempt to bind attribute
+ if (fAttributeQName.prefix != null) {
+ attributes.setURI(attrIndex, fNamespaceContext.getURI(fAttributeQName.prefix));
+ }
+ }
+ }
+
+ if (DEBUG_CONTENT_SCANNING) System.out.println("<<< scanAttribute()");
+ } // scanAttribute(XMLAttributes)
+
+
+
+ /**
+ * Scans an end element.
+ *
+ *
+ * [42] ETag ::= '</' Name S? '>'
+ *
+ *
+ * Note: This method uses the fElementQName variable.
+ * The contents of this variable will be destroyed. The caller should
+ * copy the needed information out of this variable before calling
+ * this method.
+ *
+ * @return The element depth.
+ */
+ protected int scanEndElement() throws IOException, XNIException {
+ if (DEBUG_CONTENT_SCANNING) System.out.println(">>> scanEndElement()");
+
+ // pop context
+ fElementStack.popElement(fElementQName) ;
+
+ // Take advantage of the fact that next string _should_ be "fElementQName.rawName",
+ //In scanners most of the time is consumed on checks done for XML characters, we can
+ // optimize on it and avoid the checks done for endElement,
+ //we will also avoid symbol table lookup - neeraj.bajaj@sun.com
+
+ // this should work both for namespace processing true or false...
+
+ //REVISIT: if the string is not the same as expected.. we need to do better error handling..
+ //We can skip this for now... In any case if the string doesn't match -- document is not well formed.
+ if (!fEntityScanner.skipString(fElementQName.rawname)) {
+ reportFatalError("ETagRequired", new Object[]{fElementQName.rawname});
+ }
+
+ // end
+ fEntityScanner.skipSpaces();
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError("ETagUnterminated",
+ new Object[]{fElementQName.rawname});
+ }
+ fMarkupDepth--;
+
+ //we have increased the depth for two markup "<" characters
+ fMarkupDepth--;
+
+ // check that this element was opened in the same entity
+ if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
+ reportFatalError("ElementEntityMismatch",
+ new Object[]{fCurrentElement.rawname});
+ }
+
+ // call handler
+ if (fDocumentHandler != null ) {
+
+ fDocumentHandler.endElement(fElementQName, null);
+ if (fBindNamespaces) {
+ fNamespaceContext.popContext();
+ }
+
+ }
+
+ return fMarkupDepth;
+
+ } // scanEndElement():int
+
+
+ public void reset(XMLComponentManager componentManager)
+ throws XMLConfigurationException {
+
+ super.reset(componentManager);
+ fPerformValidation = false;
+ fBindNamespaces = false;
+ }
+
+ /** Creates a content dispatcher. */
+ protected Dispatcher createContentDispatcher() {
+ return new NSContentDispatcher();
+ } // createContentDispatcher():Dispatcher
+
+ /**
+ * Dispatcher to handle content scanning.
+ */
+ protected final class NSContentDispatcher
+ extends ContentDispatcher {
+
+ /**
+ * Scan for root element hook. This method is a hook for
+ * subclasses to add code that handles scanning for the root
+ * element. This method will also attempt to remove DTD validator
+ * from the pipeline, if there is no DTD grammar. If DTD validator
+ * is no longer in the pipeline bind namespaces in the scanner.
+ *
+ *
+ * @return True if the caller should stop and return true which
+ * allows the scanner to switch to a new scanning
+ * dispatcher. A return value of false indicates that
+ * the content dispatcher should continue as normal.
+ */
+ protected boolean scanRootElementHook()
+ throws IOException, XNIException {
+
+ if (fExternalSubsetResolver != null && !fSeenDoctypeDecl
+ && !fDisallowDoctype && (fValidation || fLoadExternalDTD)) {
+ scanStartElementName();
+ resolveExternalSubsetAndRead();
+ reconfigurePipeline();
+ if (scanStartElementAfterName()) {
+ setScannerState(SCANNER_STATE_TRAILING_MISC);
+ setDispatcher(fTrailingMiscDispatcher);
+ return true;
+ }
+ }
+ else {
+ reconfigurePipeline();
+ if (scanStartElement()) {
+ setScannerState(SCANNER_STATE_TRAILING_MISC);
+ setDispatcher(fTrailingMiscDispatcher);
+ return true;
+ }
+ }
+ return false;
+
+ } // scanRootElementHook():boolean
+
+ /**
+ * Re-configures pipeline by removing the DTD validator
+ * if no DTD grammar exists. If no validator exists in the
+ * pipeline or there is no DTD grammar, namespace binding
+ * is performed by the scanner in the enclosing class.
+ */
+ private void reconfigurePipeline() {
+ if (fDTDValidator == null) {
+ fBindNamespaces = true;
+ }
+ else if (!fDTDValidator.hasGrammar()) {
+ fBindNamespaces = true;
+ fPerformValidation = fDTDValidator.validate();
+ // re-configure pipeline
+ XMLDocumentSource source = fDTDValidator.getDocumentSource();
+ XMLDocumentHandler handler = fDTDValidator.getDocumentHandler();
+ source.setDocumentHandler(handler);
+ if (handler != null)
+ handler.setDocumentSource(source);
+ fDTDValidator.setDocumentSource(null);
+ fDTDValidator.setDocumentHandler(null);
+ }
+ } // reconfigurePipeline()
+ }
+
+} // class XMLNSDocumentScannerImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XMLNamespaceBinder.java b/resources/xerces2-j-src/org/apache/xerces/impl/XMLNamespaceBinder.java
new file mode 100644
index 0000000..70c0e70
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XMLNamespaceBinder.java
@@ -0,0 +1,850 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLAttributes;
+import org.apache.xerces.xni.XMLDocumentHandler;
+import org.apache.xerces.xni.XMLLocator;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLComponent;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLDocumentFilter;
+import org.apache.xerces.xni.parser.XMLDocumentSource;
+
+/**
+ * This class performs namespace binding on the startElement and endElement
+ * method calls and passes all other methods through to the registered
+ * document handler. This class can be configured to only pass the
+ * start and end prefix mappings (start/endPrefixMapping).
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/namespaces
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ *
+ * @version $Id$
+ */
+public class XMLNamespaceBinder
+ implements XMLComponent, XMLDocumentFilter {
+
+ //
+ // Constants
+ //
+
+ // feature identifiers
+
+ /** Feature identifier: namespaces. */
+ protected static final String NAMESPACES =
+ Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
+
+ // property identifiers
+
+ /** Property identifier: symbol table. */
+ protected static final String SYMBOL_TABLE =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
+
+ /** Property identifier: error reporter. */
+ protected static final String ERROR_REPORTER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
+
+ // recognized features and properties
+
+ /** Recognized features. */
+ private static final String[] RECOGNIZED_FEATURES = {
+ NAMESPACES,
+ };
+
+ /** Feature defaults. */
+ private static final Boolean[] FEATURE_DEFAULTS = {
+ null,
+ };
+
+ /** Recognized properties. */
+ private static final String[] RECOGNIZED_PROPERTIES = {
+ SYMBOL_TABLE,
+ ERROR_REPORTER,
+ };
+
+ /** Property defaults. */
+ private static final Object[] PROPERTY_DEFAULTS = {
+ null,
+ null,
+ };
+
+ //
+ // Data
+ //
+
+ // features
+
+ /** Namespaces. */
+ protected boolean fNamespaces;
+
+ // properties
+
+ /** Symbol table. */
+ protected SymbolTable fSymbolTable;
+
+ /** Error reporter. */
+ protected XMLErrorReporter fErrorReporter;
+
+ // handlers
+
+ /** Document handler. */
+ protected XMLDocumentHandler fDocumentHandler;
+
+ protected XMLDocumentSource fDocumentSource;
+
+ // settings
+
+ /** Only pass start and end prefix mapping events. */
+ protected boolean fOnlyPassPrefixMappingEvents;
+
+ // shared context
+
+ /** Namespace context. */
+ private NamespaceContext fNamespaceContext;
+
+ // temp vars
+
+ /** Attribute QName. */
+ private final QName fAttributeQName = new QName();
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XMLNamespaceBinder() {
+ } // ()
+
+ //
+ // Public methods
+ //
+
+ // settings
+
+ /**
+ * Sets whether the namespace binder only passes the prefix mapping
+ * events to the registered document handler or passes all document
+ * events.
+ *
+ * @param onlyPassPrefixMappingEvents True to pass only the prefix
+ * mapping events; false to pass
+ * all events.
+ */
+ public void setOnlyPassPrefixMappingEvents(boolean onlyPassPrefixMappingEvents) {
+ fOnlyPassPrefixMappingEvents = onlyPassPrefixMappingEvents;
+ } // setOnlyPassPrefixMappingEvents(boolean)
+
+ /**
+ * Returns true if the namespace binder only passes the prefix mapping
+ * events to the registered document handler; false if the namespace
+ * binder passes all document events.
+ */
+ public boolean getOnlyPassPrefixMappingEvents() {
+ return fOnlyPassPrefixMappingEvents;
+ } // getOnlyPassPrefixMappingEvents():boolean
+
+ //
+ // XMLComponent methods
+ //
+
+ /**
+ * Resets the component. The component can query the component manager
+ * about any features and properties that affect the operation of the
+ * component.
+ *
+ * @param componentManager The component manager.
+ *
+ * @throws SAXException Thrown by component on initialization error.
+ * For example, if a feature or property is
+ * required for the operation of the component, the
+ * component manager may throw a
+ * SAXNotRecognizedException or a
+ * SAXNotSupportedException.
+ */
+ public void reset(XMLComponentManager componentManager)
+ throws XNIException {
+
+ // features
+ try {
+ fNamespaces = componentManager.getFeature(NAMESPACES);
+ }
+ catch (XMLConfigurationException e) {
+ fNamespaces = true;
+ }
+
+ // Xerces properties
+ fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
+ fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
+
+ } // reset(XMLComponentManager)
+
+ /**
+ * Returns a list of feature identifiers that are recognized by
+ * this component. This method may return null if no features
+ * are recognized by this component.
+ */
+ public String[] getRecognizedFeatures() {
+ return (String[])(RECOGNIZED_FEATURES.clone());
+ } // getRecognizedFeatures():String[]
+
+ /**
+ * Sets the state of a feature. This method is called by the component
+ * manager any time after reset when a feature changes state.
+ *
+ * Note: Components should silently ignore features
+ * that do not affect the operation of the component.
+ *
+ * @param featureId The feature identifier.
+ * @param state The state of the feature.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setFeature(String featureId, boolean state)
+ throws XMLConfigurationException {
+ } // setFeature(String,boolean)
+
+ /**
+ * Returns a list of property identifiers that are recognized by
+ * this component. This method may return null if no properties
+ * are recognized by this component.
+ */
+ public String[] getRecognizedProperties() {
+ return (String[])(RECOGNIZED_PROPERTIES.clone());
+ } // getRecognizedProperties():String[]
+
+ /**
+ * Sets the value of a property during parsing.
+ *
+ * @param propertyId
+ * @param value
+ */
+ public void setProperty(String propertyId, Object value)
+ throws XMLConfigurationException {
+
+ // Xerces properties
+ if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
+ final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
+
+ if (suffixLength == Constants.SYMBOL_TABLE_PROPERTY.length() &&
+ propertyId.endsWith(Constants.SYMBOL_TABLE_PROPERTY)) {
+ fSymbolTable = (SymbolTable)value;
+ }
+ else if (suffixLength == Constants.ERROR_REPORTER_PROPERTY.length() &&
+ propertyId.endsWith(Constants.ERROR_REPORTER_PROPERTY)) {
+ fErrorReporter = (XMLErrorReporter)value;
+ }
+ return;
+ }
+
+ } // setProperty(String,Object)
+
+ /**
+ * Returns the default state for a feature, or null if this
+ * component does not want to report a default value for this
+ * feature.
+ *
+ * @param featureId The feature identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Boolean getFeatureDefault(String featureId) {
+ for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
+ if (RECOGNIZED_FEATURES[i].equals(featureId)) {
+ return FEATURE_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getFeatureDefault(String):Boolean
+
+ /**
+ * Returns the default state for a property, or null if this
+ * component does not want to report a default value for this
+ * property.
+ *
+ * @param propertyId The property identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Object getPropertyDefault(String propertyId) {
+ for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
+ if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
+ return PROPERTY_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getPropertyDefault(String):Object
+
+ //
+ // XMLDocumentSource methods
+ //
+
+ /** Sets the document handler to receive information about the document. */
+ public void setDocumentHandler(XMLDocumentHandler documentHandler) {
+ fDocumentHandler = documentHandler;
+ } // setDocumentHandler(XMLDocumentHandler)
+
+ /** Returns the document handler */
+ public XMLDocumentHandler getDocumentHandler() {
+ return fDocumentHandler;
+ } // setDocumentHandler(XMLDocumentHandler)
+
+
+ //
+ // XMLDocumentHandler methods
+ //
+
+ /** Sets the document source */
+ public void setDocumentSource(XMLDocumentSource source){
+ fDocumentSource = source;
+ } // setDocumentSource
+
+ /** Returns the document source */
+ public XMLDocumentSource getDocumentSource (){
+ return fDocumentSource;
+ } // getDocumentSource
+
+
+ /**
+ * This method notifies the start of a general entity.
+ *
+ * Note: This method is not called for entity references
+ * appearing as part of attribute values.
+ *
+ * @param name The name of the general entity.
+ * @param identifier The resource identifier.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal entities or a document entity that is
+ * parsed from a java.io.Reader).
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException Thrown by handler to signal an error.
+ */
+ public void startGeneralEntity(String name,
+ XMLResourceIdentifier identifier,
+ String encoding, Augmentations augs)
+ throws XNIException {
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
+ }
+ } // startEntity(String,String,String,String,String)
+
+ /**
+ * Notifies of the presence of a TextDecl line in an entity. If present,
+ * this method will be called immediately following the startEntity call.
+ *
+ * Note: This method will never be called for the
+ * document entity; it is only called for external general entities
+ * referenced in document content.
+ *
+ * Note: This method is not called for entity references
+ * appearing as part of attribute values.
+ *
+ * @param version The XML version, or null if not specified.
+ * @param encoding The IANA encoding name of the entity.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void textDecl(String version, String encoding, Augmentations augs)
+ throws XNIException {
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.textDecl(version, encoding, augs);
+ }
+ } // textDecl(String,String)
+
+ /**
+ * The start of the document.
+ *
+ * @param locator The system identifier of the entity if the entity
+ * is external, null otherwise.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal entities or a document entity that is
+ * parsed from a java.io.Reader).
+ * @param namespaceContext
+ * The namespace context in effect at the
+ * start of this document.
+ * This object represents the current context.
+ * Implementors of this class are responsible
+ * for copying the namespace bindings from the
+ * the current context (and its parent contexts)
+ * if that information is important.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startDocument(XMLLocator locator, String encoding,
+ NamespaceContext namespaceContext, Augmentations augs)
+ throws XNIException {
+ fNamespaceContext = namespaceContext;
+
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
+ }
+ } // startDocument(XMLLocator,String)
+
+ /**
+ * Notifies of the presence of an XMLDecl line in the document. If
+ * present, this method will be called immediately following the
+ * startDocument call.
+ *
+ * @param version The XML version.
+ * @param encoding The IANA encoding name of the document, or null if
+ * not specified.
+ * @param standalone The standalone value, or null if not specified.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void xmlDecl(String version, String encoding, String standalone, Augmentations augs)
+ throws XNIException {
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
+ }
+ } // xmlDecl(String,String,String)
+
+ /**
+ * Notifies of the presence of the DOCTYPE line in the document.
+ *
+ * @param rootElement The name of the root element.
+ * @param publicId The public identifier if an external DTD or null
+ * if the external DTD is specified using SYSTEM.
+ * @param systemId The system identifier if an external DTD, null
+ * otherwise.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void doctypeDecl(String rootElement,
+ String publicId, String systemId, Augmentations augs)
+ throws XNIException {
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
+ }
+ } // doctypeDecl(String,String,String)
+
+ /**
+ * A comment.
+ *
+ * @param text The text in the comment.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by application to signal an error.
+ */
+ public void comment(XMLString text, Augmentations augs) throws XNIException {
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.comment(text, augs);
+ }
+ } // comment(XMLString)
+
+ /**
+ * A processing instruction. Processing instructions consist of a
+ * target name and, optionally, text data. The data is only meaningful
+ * to the application.
+ *
+ * Typically, a processing instruction's data will contain a series
+ * of pseudo-attributes. These pseudo-attributes follow the form of
+ * element attributes but are not parsed or presented
+ * to the application as anything other than text. The application is
+ * responsible for parsing the data.
+ *
+ * @param target The target.
+ * @param data The data or null if none specified.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void processingInstruction(String target, XMLString data, Augmentations augs)
+ throws XNIException {
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.processingInstruction(target, data, augs);
+ }
+ } // processingInstruction(String,XMLString)
+
+
+ /**
+ * Binds the namespaces. This method will handle calling the
+ * document handler to start the prefix mappings.
+ *
+ * Note: This method makes use of the
+ * fAttributeQName variable. Any contents of the variable will
+ * be destroyed. Caller should copy the values out of this
+ * temporary variable before calling this method.
+ *
+ * @param element The name of the element.
+ * @param attributes The element attributes.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
+ throws XNIException {
+
+ if (fNamespaces) {
+ handleStartElement(element, attributes, augs, false);
+ }
+ else if (fDocumentHandler != null) {
+ fDocumentHandler.startElement(element, attributes, augs);
+ }
+
+
+ } // startElement(QName,XMLAttributes)
+
+ /**
+ * An empty element.
+ *
+ * @param element The name of the element.
+ * @param attributes The element attributes.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
+ throws XNIException {
+
+ if (fNamespaces) {
+ handleStartElement(element, attributes, augs, true);
+ handleEndElement(element, augs, true);
+ }
+ else if (fDocumentHandler != null) {
+ fDocumentHandler.emptyElement(element, attributes, augs);
+ }
+
+ } // emptyElement(QName,XMLAttributes)
+
+ /**
+ * Character content.
+ *
+ * @param text The content.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void characters(XMLString text, Augmentations augs) throws XNIException {
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.characters(text, augs);
+ }
+ } // characters(XMLString)
+
+ /**
+ * Ignorable whitespace. For this method to be called, the document
+ * source must have some way of determining that the text containing
+ * only whitespace characters should be considered ignorable. For
+ * example, the validator can determine if a length of whitespace
+ * characters in the document are ignorable based on the element
+ * content model.
+ *
+ * @param text The ignorable whitespace.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.ignorableWhitespace(text, augs);
+ }
+ } // ignorableWhitespace(XMLString)
+
+ /**
+ * The end of an element.
+ *
+ * @param element The name of the element.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endElement(QName element, Augmentations augs) throws XNIException {
+
+ if (fNamespaces) {
+ handleEndElement(element, augs, false);
+ }
+ else if (fDocumentHandler != null) {
+ fDocumentHandler.endElement(element, augs);
+ }
+
+ } // endElement(QName)
+
+ /**
+ * The start of a CDATA section.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startCDATA(Augmentations augs) throws XNIException {
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.startCDATA(augs);
+ }
+ } // startCDATA()
+
+ /**
+ * The end of a CDATA section.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endCDATA(Augmentations augs) throws XNIException {
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.endCDATA(augs);
+ }
+ } // endCDATA()
+
+ /**
+ * The end of the document.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endDocument(Augmentations augs) throws XNIException {
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.endDocument(augs);
+ }
+ } // endDocument()
+
+ /**
+ * This method notifies the end of a general entity.
+ *
+ * Note: This method is not called for entity references
+ * appearing as part of attribute values.
+ *
+ * @param name The name of the entity.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ fDocumentHandler.endGeneralEntity(name, augs);
+ }
+ } // endEntity(String)
+
+ //
+ // Protected methods
+ //
+
+ /** Handles start element. */
+ protected void handleStartElement(QName element, XMLAttributes attributes,
+ Augmentations augs,
+ boolean isEmpty) throws XNIException {
+
+ // add new namespace context
+ fNamespaceContext.pushContext();
+
+ if (element.prefix == XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementXMLNSPrefix",
+ new Object[]{element.rawname},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // search for new namespace bindings
+ int length = attributes.getLength();
+ for (int i = 0; i < length; i++) {
+ String localpart = attributes.getLocalName(i);
+ String prefix = attributes.getPrefix(i);
+ // when it's of form xmlns="..." or xmlns:prefix="...",
+ // it's a namespace declaration. but prefix:xmlns="..." isn't.
+ if (prefix == XMLSymbols.PREFIX_XMLNS ||
+ prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) {
+
+ // get the internalized value of this attribute
+ String uri = fSymbolTable.addSymbol(attributes.getValue(i));
+
+ // 1. "xmlns" can't be bound to any namespace
+ if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXMLNS",
+ new Object[]{attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // 2. the namespace for "xmlns" can't be bound to any prefix
+ if (uri == NamespaceContext.XMLNS_URI) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXMLNS",
+ new Object[]{attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // 3. "xml" can't be bound to any other namespace than it's own
+ if (localpart == XMLSymbols.PREFIX_XML) {
+ if (uri != NamespaceContext.XML_URI) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXML",
+ new Object[]{attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ // 4. the namespace for "xml" can't be bound to any other prefix
+ else {
+ if (uri ==NamespaceContext.XML_URI) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXML",
+ new Object[]{attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+
+ prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING;
+
+ // http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix
+ // We should only report an error if there is a prefix,
+ // that is, the local part is not "xmlns". -SG
+ // Since this is an error condition in XML 1.0,
+ // and should be relatively uncommon in XML 1.1,
+ // making this test into a method call to reuse code
+ // should be acceptable. - NG
+ if(prefixBoundToNullURI(uri, localpart)) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "EmptyPrefixedAttName",
+ new Object[]{attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ continue;
+ }
+
+ // declare prefix in context
+ fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null);
+
+ }
+ }
+
+ // bind the element
+ String prefix = element.prefix != null
+ ? element.prefix : XMLSymbols.EMPTY_STRING;
+ element.uri = fNamespaceContext.getURI(prefix);
+ if (element.prefix == null && element.uri != null) {
+ element.prefix = XMLSymbols.EMPTY_STRING;
+ }
+ if (element.prefix != null && element.uri == null) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementPrefixUnbound",
+ new Object[]{element.prefix, element.rawname},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // bind the attributes
+ for (int i = 0; i < length; i++) {
+ attributes.getName(i, fAttributeQName);
+ String aprefix = fAttributeQName.prefix != null
+ ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
+ String arawname = fAttributeQName.rawname;
+ if (arawname == XMLSymbols.PREFIX_XMLNS) {
+ fAttributeQName.uri = fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS);
+ attributes.setName(i, fAttributeQName);
+ }
+ else if (aprefix != XMLSymbols.EMPTY_STRING) {
+ fAttributeQName.uri = fNamespaceContext.getURI(aprefix);
+ if (fAttributeQName.uri == null) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributePrefixUnbound",
+ new Object[]{element.rawname,arawname,aprefix},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ attributes.setName(i, fAttributeQName);
+ }
+ }
+
+ // verify that duplicate attributes don't exist
+ // Example:
+ int attrCount = attributes.getLength();
+ for (int i = 0; i < attrCount - 1; i++) {
+ String auri = attributes.getURI(i);
+ if (auri == null || auri == NamespaceContext.XMLNS_URI) {
+ continue;
+ }
+ String alocalpart = attributes.getLocalName(i);
+ for (int j = i + 1; j < attrCount; j++) {
+ String blocalpart = attributes.getLocalName(j);
+ String buri = attributes.getURI(j);
+ if (alocalpart == blocalpart && auri == buri) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNSNotUnique",
+ new Object[]{element.rawname,alocalpart, auri},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ }
+
+ // call handler
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ if (isEmpty) {
+ fDocumentHandler.emptyElement(element, attributes, augs);
+ }
+ else {
+ fDocumentHandler.startElement(element, attributes, augs);
+ }
+ }
+
+
+ } // handleStartElement(QName,XMLAttributes,boolean)
+
+ /** Handles end element. */
+ protected void handleEndElement(QName element, Augmentations augs, boolean isEmpty)
+ throws XNIException {
+
+ // bind element
+ String eprefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING;
+ element.uri = fNamespaceContext.getURI(eprefix);
+ if (element.uri != null) {
+ element.prefix = eprefix;
+ }
+
+ // call handlers
+ if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
+ if (!isEmpty) {
+ fDocumentHandler.endElement(element, augs);
+ }
+ }
+
+ // pop context
+ fNamespaceContext.popContext();
+
+ } // handleEndElement(QName,boolean)
+
+ // returns true iff the given prefix is bound to "" *and*
+ // this is disallowed by the version of XML namespaces in use.
+ protected boolean prefixBoundToNullURI(String uri, String localpart) {
+ return (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS);
+ } // prefixBoundToNullURI(String, String): boolean
+
+} // class XMLNamespaceBinder
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XMLScanner.java b/resources/xerces2-j-src/org/apache/xerces/impl/XMLScanner.java
new file mode 100644
index 0000000..2c4026a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XMLScanner.java
@@ -0,0 +1,1510 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.io.IOException;
+
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.util.XMLResourceIdentifierImpl;
+import org.apache.xerces.util.XMLStringBuffer;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLComponent;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+
+/**
+ * This class is responsible for holding scanning methods common to
+ * scanning the XML document structure and content as well as the DTD
+ * structure and content. Both XMLDocumentScanner and XMLDTDScanner inherit
+ * from this base class.
+ *
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/validation
+ * - http://xml.org/sax/features/namespaces
+ * - http://apache.org/xml/features/scanner/notify-char-refs
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/entity-manager
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ * @author Arnaud Le Hors, IBM
+ * @author Eric Ye, IBM
+ *
+ * @version $Id$
+ */
+public abstract class XMLScanner
+ implements XMLComponent {
+
+ //
+ // Constants
+ //
+
+ // feature identifiers
+
+ /** Feature identifier: validation. */
+ protected static final String VALIDATION =
+ Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
+
+ /** Feature identifier: namespaces. */
+ protected static final String NAMESPACES =
+ Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
+
+ /** Feature identifier: notify character references. */
+ protected static final String NOTIFY_CHAR_REFS =
+ Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_CHAR_REFS_FEATURE;
+
+ protected static final String PARSER_SETTINGS =
+ Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
+
+ // property identifiers
+
+ /** Property identifier: symbol table. */
+ protected static final String SYMBOL_TABLE =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
+
+ /** Property identifier: error reporter. */
+ protected static final String ERROR_REPORTER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
+
+ /** Property identifier: entity manager. */
+ protected static final String ENTITY_MANAGER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
+
+ // debugging
+
+ /** Debug attribute normalization. */
+ protected static final boolean DEBUG_ATTR_NORMALIZATION = false;
+
+ //
+ // Data
+ //
+
+
+ // features
+
+ /**
+ * Validation. This feature identifier is:
+ * http://xml.org/sax/features/validation
+ */
+ protected boolean fValidation = false;
+
+ /** Namespaces. */
+ protected boolean fNamespaces;
+
+ /** Character references notification. */
+ protected boolean fNotifyCharRefs = false;
+
+ /** Internal parser-settings feature */
+ protected boolean fParserSettings = true;
+
+ // properties
+
+ /** Symbol table. */
+ protected SymbolTable fSymbolTable;
+
+ /** Error reporter. */
+ protected XMLErrorReporter fErrorReporter;
+
+ /** Entity manager. */
+ protected XMLEntityManager fEntityManager;
+
+ // protected data
+
+ /** Entity scanner. */
+ protected XMLEntityScanner fEntityScanner;
+
+ /** Entity depth. */
+ protected int fEntityDepth;
+
+ /** Literal value of the last character refence scanned. */
+ protected String fCharRefLiteral = null;
+
+ /** Scanning attribute. */
+ protected boolean fScanningAttribute;
+
+ /** Report entity boundary. */
+ protected boolean fReportEntity;
+
+ // symbols
+
+ /** Symbol: "version". */
+ protected final static String fVersionSymbol = "version".intern();
+
+ /** Symbol: "encoding". */
+ protected final static String fEncodingSymbol = "encoding".intern();
+
+ /** Symbol: "standalone". */
+ protected final static String fStandaloneSymbol = "standalone".intern();
+
+ /** Symbol: "amp". */
+ protected final static String fAmpSymbol = "amp".intern();
+
+ /** Symbol: "lt". */
+ protected final static String fLtSymbol = "lt".intern();
+
+ /** Symbol: "gt". */
+ protected final static String fGtSymbol = "gt".intern();
+
+ /** Symbol: "quot". */
+ protected final static String fQuotSymbol = "quot".intern();
+
+ /** Symbol: "apos". */
+ protected final static String fAposSymbol = "apos".intern();
+
+ // temporary variables
+
+ // NOTE: These objects are private to help prevent accidental modification
+ // of values by a subclass. If there were protected *and* the sub-
+ // modified the values, it would be difficult to track down the real
+ // cause of the bug. By making these private, we avoid this
+ // possibility.
+
+ /** String. */
+ private final XMLString fString = new XMLString();
+
+ /** String buffer. */
+ private final XMLStringBuffer fStringBuffer = new XMLStringBuffer();
+
+ /** String buffer. */
+ private final XMLStringBuffer fStringBuffer2 = new XMLStringBuffer();
+
+ /** String buffer. */
+ private final XMLStringBuffer fStringBuffer3 = new XMLStringBuffer();
+
+ // temporary location for Resource identification information.
+ protected final XMLResourceIdentifierImpl fResourceIdentifier = new XMLResourceIdentifierImpl();
+
+ //
+ // XMLComponent methods
+ //
+
+ /**
+ *
+ *
+ * @param componentManager The component manager.
+ *
+ * @throws SAXException Throws exception if required features and
+ * properties cannot be found.
+ */
+ public void reset(XMLComponentManager componentManager)
+ throws XMLConfigurationException {
+
+ try {
+ fParserSettings = componentManager.getFeature(PARSER_SETTINGS);
+ } catch (XMLConfigurationException e) {
+ fParserSettings = true;
+ }
+
+ if (!fParserSettings) {
+ // parser settings have not been changed
+ init();
+ return;
+ }
+
+ // Xerces properties
+ fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
+ fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
+ fEntityManager = (XMLEntityManager)componentManager.getProperty(ENTITY_MANAGER);
+
+ // sax features
+ try {
+ fValidation = componentManager.getFeature(VALIDATION);
+ }
+ catch (XMLConfigurationException e) {
+ fValidation = false;
+ }
+ try {
+ fNamespaces = componentManager.getFeature(NAMESPACES);
+ }
+ catch (XMLConfigurationException e) {
+ fNamespaces = true;
+ }
+ try {
+ fNotifyCharRefs = componentManager.getFeature(NOTIFY_CHAR_REFS);
+ }
+ catch (XMLConfigurationException e) {
+ fNotifyCharRefs = false;
+ }
+
+ init();
+
+ } // reset(XMLComponentManager)
+
+ /**
+ * Sets the value of a property during parsing.
+ *
+ * @param propertyId
+ * @param value
+ */
+ public void setProperty(String propertyId, Object value)
+ throws XMLConfigurationException {
+
+ // Xerces properties
+ if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
+ final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
+
+ if (suffixLength == Constants.SYMBOL_TABLE_PROPERTY.length() &&
+ propertyId.endsWith(Constants.SYMBOL_TABLE_PROPERTY)) {
+ fSymbolTable = (SymbolTable)value;
+ }
+ else if (suffixLength == Constants.ERROR_REPORTER_PROPERTY.length() &&
+ propertyId.endsWith(Constants.ERROR_REPORTER_PROPERTY)) {
+ fErrorReporter = (XMLErrorReporter)value;
+ }
+ else if (suffixLength == Constants.ENTITY_MANAGER_PROPERTY.length() &&
+ propertyId.endsWith(Constants.ENTITY_MANAGER_PROPERTY)) {
+ fEntityManager = (XMLEntityManager)value;
+ }
+ }
+
+ } // setProperty(String,Object)
+
+ /*
+ * Sets the feature of the scanner.
+ */
+ public void setFeature(String featureId, boolean value)
+ throws XMLConfigurationException {
+
+ if (VALIDATION.equals(featureId)) {
+ fValidation = value;
+ } else if (NOTIFY_CHAR_REFS.equals(featureId)) {
+ fNotifyCharRefs = value;
+ }
+ }
+
+ /*
+ * Gets the state of the feature of the scanner.
+ */
+ public boolean getFeature(String featureId)
+ throws XMLConfigurationException {
+
+ if (VALIDATION.equals(featureId)) {
+ return fValidation;
+ } else if (NOTIFY_CHAR_REFS.equals(featureId)) {
+ return fNotifyCharRefs;
+ }
+ throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, featureId);
+ }
+
+ //
+ // Protected methods
+ //
+
+ // anybody calling this had better have set Symtoltable!
+ protected void reset() {
+ init();
+
+ // DTD preparsing defaults:
+ fValidation = true;
+ fNotifyCharRefs = false;
+
+ }
+
+ // common scanning methods
+
+ /**
+ * Scans an XML or text declaration.
+ *
+ *
+ * [23] XMLDecl ::= ''
+ * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
+ * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
+ * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
+ * [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'")
+ * | ('"' ('yes' | 'no') '"'))
+ *
+ * [77] TextDecl ::= ''
+ *
+ *
+ * @param scanningTextDecl True if a text declaration is to
+ * be scanned instead of an XML
+ * declaration.
+ * @param pseudoAttributeValues An array of size 3 to return the version,
+ * encoding and standalone pseudo attribute values
+ * (in that order).
+ *
+ * Note: This method uses fString, anything in it
+ * at the time of calling is lost.
+ */
+ protected void scanXMLDeclOrTextDecl(boolean scanningTextDecl,
+ String[] pseudoAttributeValues)
+ throws IOException, XNIException {
+
+ // pseudo-attribute values
+ String version = null;
+ String encoding = null;
+ String standalone = null;
+
+ // scan pseudo-attributes
+ final int STATE_VERSION = 0;
+ final int STATE_ENCODING = 1;
+ final int STATE_STANDALONE = 2;
+ final int STATE_DONE = 3;
+ int state = STATE_VERSION;
+
+ boolean dataFoundForTarget = false;
+ boolean sawSpace = fEntityScanner.skipDeclSpaces();
+ // since pseudoattributes are *not* attributes,
+ // their quotes don't need to be preserved in external parameter entities.
+ // the XMLEntityScanner#scanLiteral method will continue to
+ // emit -1 in such cases when it finds a quote; this is
+ // fine for other methods that parse scanned entities,
+ // but not for the scanning of pseudoattributes. So,
+ // temporarily, we must mark the current entity as not being "literal"
+ XMLEntityManager.ScannedEntity currEnt = fEntityManager.getCurrentEntity();
+ boolean currLiteral = currEnt.literal;
+ currEnt.literal = false;
+ while (fEntityScanner.peekChar() != '?') {
+ dataFoundForTarget = true;
+ String name = scanPseudoAttribute(scanningTextDecl, fString);
+ switch (state) {
+ case STATE_VERSION: {
+ if (name == fVersionSymbol) {
+ if (!sawSpace) {
+ reportFatalError(scanningTextDecl
+ ? "SpaceRequiredBeforeVersionInTextDecl"
+ : "SpaceRequiredBeforeVersionInXMLDecl",
+ null);
+ }
+ version = fString.toString();
+ state = STATE_ENCODING;
+ if (!versionSupported(version)) {
+ reportFatalError(getVersionNotSupportedKey(),
+ new Object[]{version});
+ }
+ }
+ else if (name == fEncodingSymbol) {
+ if (!scanningTextDecl) {
+ reportFatalError("VersionInfoRequired", null);
+ }
+ if (!sawSpace) {
+ reportFatalError(scanningTextDecl
+ ? "SpaceRequiredBeforeEncodingInTextDecl"
+ : "SpaceRequiredBeforeEncodingInXMLDecl",
+ null);
+ }
+ encoding = fString.toString();
+ state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
+ }
+ else {
+ if (scanningTextDecl) {
+ reportFatalError("EncodingDeclRequired", null);
+ }
+ else {
+ reportFatalError("VersionInfoRequired", null);
+ }
+ }
+ break;
+ }
+ case STATE_ENCODING: {
+ if (name == fEncodingSymbol) {
+ if (!sawSpace) {
+ reportFatalError(scanningTextDecl
+ ? "SpaceRequiredBeforeEncodingInTextDecl"
+ : "SpaceRequiredBeforeEncodingInXMLDecl",
+ null);
+ }
+ encoding = fString.toString();
+ state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
+ // TODO: check encoding name; set encoding on
+ // entity scanner
+ }
+ else if (!scanningTextDecl && name == fStandaloneSymbol) {
+ if (!sawSpace) {
+ reportFatalError("SpaceRequiredBeforeStandalone",
+ null);
+ }
+ standalone = fString.toString();
+ state = STATE_DONE;
+ if (!standalone.equals("yes") && !standalone.equals("no")) {
+ reportFatalError("SDDeclInvalid", new Object[] {standalone});
+ }
+ }
+ else {
+ reportFatalError("EncodingDeclRequired", null);
+ }
+ break;
+ }
+ case STATE_STANDALONE: {
+ if (name == fStandaloneSymbol) {
+ if (!sawSpace) {
+ reportFatalError("SpaceRequiredBeforeStandalone",
+ null);
+ }
+ standalone = fString.toString();
+ state = STATE_DONE;
+ if (!standalone.equals("yes") && !standalone.equals("no")) {
+ reportFatalError("SDDeclInvalid", new Object[] {standalone});
+ }
+ }
+ else {
+ reportFatalError("EncodingDeclRequired", null);
+ }
+ break;
+ }
+ default: {
+ reportFatalError("NoMorePseudoAttributes", null);
+ }
+ }
+ sawSpace = fEntityScanner.skipDeclSpaces();
+ }
+ // restore original literal value
+ if(currLiteral)
+ currEnt.literal = true;
+ // REVISIT: should we remove this error reporting?
+ if (scanningTextDecl && state != STATE_DONE) {
+ reportFatalError("MorePseudoAttributes", null);
+ }
+
+ // If there is no data in the xml or text decl then we fail to report error
+ // for version or encoding info above.
+ if (scanningTextDecl) {
+ if (!dataFoundForTarget && encoding == null) {
+ reportFatalError("EncodingDeclRequired", null);
+ }
+ }
+ else {
+ if (!dataFoundForTarget && version == null) {
+ reportFatalError("VersionInfoRequired", null);
+ }
+ }
+
+ // end
+ if (!fEntityScanner.skipChar('?')) {
+ reportFatalError("XMLDeclUnterminated", null);
+ }
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError("XMLDeclUnterminated", null);
+
+ }
+
+ // fill in return array
+ pseudoAttributeValues[0] = version;
+ pseudoAttributeValues[1] = encoding;
+ pseudoAttributeValues[2] = standalone;
+
+ } // scanXMLDeclOrTextDecl(boolean)
+
+ /**
+ * Scans a pseudo attribute.
+ *
+ * @param scanningTextDecl True if scanning this pseudo-attribute for a
+ * TextDecl; false if scanning XMLDecl. This
+ * flag is needed to report the correct type of
+ * error.
+ * @param value The string to fill in with the attribute
+ * value.
+ *
+ * @return The name of the attribute
+ *
+ * Note: This method uses fStringBuffer2, anything in it
+ * at the time of calling is lost.
+ */
+ public String scanPseudoAttribute(boolean scanningTextDecl,
+ XMLString value)
+ throws IOException, XNIException {
+
+ // REVISIT: This method is used for generic scanning of
+ // pseudo attributes, but since there are only three such
+ // attributes: version, encoding, and standalone there are
+ // for performant ways of scanning them. Every decl must
+ // have a version, and in TextDecls this version must
+ // be followed by an encoding declaration. Also the
+ // methods we invoke on the scanners allow non-ASCII
+ // characters to be parsed in the decls, but since
+ // we don't even know what the actual encoding of the
+ // document is until we scan the encoding declaration
+ // you cannot reliably read any characters outside
+ // of the ASCII range here. -- mrglavas
+ String name = scanPseudoAttributeName();
+ XMLEntityManager.print(fEntityManager.getCurrentEntity());
+ if (name == null) {
+ reportFatalError("PseudoAttrNameExpected", null);
+ }
+ fEntityScanner.skipDeclSpaces();
+ if (!fEntityScanner.skipChar('=')) {
+ reportFatalError(scanningTextDecl ? "EqRequiredInTextDecl"
+ : "EqRequiredInXMLDecl", new Object[]{name});
+ }
+ fEntityScanner.skipDeclSpaces();
+ int quote = fEntityScanner.peekChar();
+ if (quote != '\'' && quote != '"') {
+ reportFatalError(scanningTextDecl ? "QuoteRequiredInTextDecl"
+ : "QuoteRequiredInXMLDecl" , new Object[]{name});
+ }
+ fEntityScanner.scanChar();
+ int c = fEntityScanner.scanLiteral(quote, value);
+ if (c != quote) {
+ fStringBuffer2.clear();
+ do {
+ fStringBuffer2.append(value);
+ if (c != -1) {
+ if (c == '&' || c == '%' || c == '<' || c == ']') {
+ fStringBuffer2.append((char)fEntityScanner.scanChar());
+ }
+ // REVISIT: Even if you could reliably read non-ASCII chars
+ // why bother scanning for surrogates here? Only ASCII chars
+ // match the productions in XMLDecls and TextDecls. -- mrglavas
+ else if (XMLChar.isHighSurrogate(c)) {
+ scanSurrogates(fStringBuffer2);
+ }
+ else if (isInvalidLiteral(c)) {
+ String key = scanningTextDecl
+ ? "InvalidCharInTextDecl" : "InvalidCharInXMLDecl";
+ reportFatalError(key,
+ new Object[] {Integer.toString(c, 16)});
+ fEntityScanner.scanChar();
+ }
+ }
+ c = fEntityScanner.scanLiteral(quote, value);
+ } while (c != quote);
+ fStringBuffer2.append(value);
+ value.setValues(fStringBuffer2);
+ }
+ if (!fEntityScanner.skipChar(quote)) {
+ reportFatalError(scanningTextDecl ? "CloseQuoteMissingInTextDecl"
+ : "CloseQuoteMissingInXMLDecl",
+ new Object[]{name});
+ }
+
+ // return
+ return name;
+
+ } // scanPseudoAttribute(XMLString):String
+
+ /**
+ * Scans the name of a pseudo attribute. The only legal names
+ * in XML 1.0/1.1 documents are 'version', 'encoding' and 'standalone'.
+ *
+ * @return the name of the pseudo attribute or null
+ * if a legal pseudo attribute name could not be scanned.
+ */
+ private String scanPseudoAttributeName() throws IOException, XNIException {
+ final int ch = fEntityScanner.peekChar();
+ switch (ch) {
+ case 'v':
+ if (fEntityScanner.skipString(fVersionSymbol)) {
+ return fVersionSymbol;
+ }
+ break;
+ case 'e':
+ if (fEntityScanner.skipString(fEncodingSymbol)) {
+ return fEncodingSymbol;
+ }
+ break;
+ case 's':
+ if (fEntityScanner.skipString(fStandaloneSymbol)) {
+ return fStandaloneSymbol;
+ }
+ break;
+ }
+ return null;
+ } // scanPseudoAttributeName()
+
+ /**
+ * Scans a processing instruction.
+ *
+ *
+ * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
+ * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
+ *
+ * Note: This method uses fString, anything in it
+ * at the time of calling is lost.
+ */
+ protected void scanPI() throws IOException, XNIException {
+
+ // target
+ fReportEntity = false;
+ String target = null;
+ if(fNamespaces) {
+ target = fEntityScanner.scanNCName();
+ } else {
+ target = fEntityScanner.scanName();
+ }
+ if (target == null) {
+ reportFatalError("PITargetRequired", null);
+ }
+
+ // scan data
+ scanPIData(target, fString);
+ fReportEntity = true;
+
+ } // scanPI()
+
+ /**
+ * Scans a processing data. This is needed to handle the situation
+ * where a document starts with a processing instruction whose
+ * target name starts with "xml". (e.g. xmlfoo)
+ *
+ * Note: This method uses fStringBuffer, anything in it
+ * at the time of calling is lost.
+ *
+ * @param target The PI target
+ * @param data The string to fill in with the data
+ */
+ protected void scanPIData(String target, XMLString data)
+ throws IOException, XNIException {
+
+ // check target
+ if (target.length() == 3) {
+ char c0 = Character.toLowerCase(target.charAt(0));
+ char c1 = Character.toLowerCase(target.charAt(1));
+ char c2 = Character.toLowerCase(target.charAt(2));
+ if (c0 == 'x' && c1 == 'm' && c2 == 'l') {
+ reportFatalError("ReservedPITarget", null);
+ }
+ }
+
+ // spaces
+ if (!fEntityScanner.skipSpaces()) {
+ if (fEntityScanner.skipString("?>")) {
+ // we found the end, there is no data
+ data.clear();
+ return;
+ }
+ else {
+ if(fNamespaces && fEntityScanner.peekChar() == ':') {
+ fEntityScanner.scanChar();
+ XMLStringBuffer colonName = new XMLStringBuffer(target);
+ colonName.append(':');
+ String str = fEntityScanner.scanName();
+ if (str != null)
+ colonName.append(str);
+ reportFatalError("ColonNotLegalWithNS", new Object[] {colonName.toString()});
+ fEntityScanner.skipSpaces();
+ } else {
+ // if there is data there should be some space
+ reportFatalError("SpaceRequiredInPI", null);
+ }
+ }
+ }
+
+ fStringBuffer.clear();
+ // data
+ if (fEntityScanner.scanData("?>", fStringBuffer)) {
+ do {
+ int c = fEntityScanner.peekChar();
+ if (c != -1) {
+ if (XMLChar.isHighSurrogate(c)) {
+ scanSurrogates(fStringBuffer);
+ }
+ else if (isInvalidLiteral(c)) {
+ reportFatalError("InvalidCharInPI",
+ new Object[]{Integer.toHexString(c)});
+ fEntityScanner.scanChar();
+ }
+ }
+ } while (fEntityScanner.scanData("?>", fStringBuffer));
+ }
+ data.setValues(fStringBuffer);
+
+ } // scanPIData(String,XMLString)
+
+ /**
+ * Scans a comment.
+ *
+ *
+ * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
+ *
+ *
+ * Note: Called after scanning past '<!--'
+ * Note: This method uses fString, anything in it
+ * at the time of calling is lost.
+ *
+ * @param text The buffer to fill in with the text.
+ */
+ protected void scanComment(XMLStringBuffer text)
+ throws IOException, XNIException {
+
+ // text
+ // REVISIT: handle invalid character, eof
+ text.clear();
+ while (fEntityScanner.scanData("--", text)) {
+ int c = fEntityScanner.peekChar();
+ if (c != -1) {
+ if (XMLChar.isHighSurrogate(c)) {
+ scanSurrogates(text);
+ }
+ else if (isInvalidLiteral(c)) {
+ reportFatalError("InvalidCharInComment",
+ new Object[] { Integer.toHexString(c) });
+ fEntityScanner.scanChar();
+ }
+ }
+ }
+ if (!fEntityScanner.skipChar('>')) {
+ reportFatalError("DashDashInComment", null);
+ }
+
+ } // scanComment()
+
+ /**
+ * Scans an attribute value and normalizes whitespace converting all
+ * whitespace characters to space characters.
+ *
+ * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"
+ *
+ * @param value The XMLString to fill in with the value.
+ * @param nonNormalizedValue The XMLString to fill in with the
+ * non-normalized value.
+ * @param atName The name of the attribute being parsed (for error msgs).
+ * @param checkEntities true if undeclared entities should be reported as VC violation,
+ * false if undeclared entities should be reported as WFC violation.
+ * @param eleName The name of element to which this attribute belongs.
+ *
+ * @return true if the non-normalized and normalized value are the same
+ *
+ * Note: This method uses fStringBuffer2, anything in it
+ * at the time of calling is lost.
+ **/
+ protected boolean scanAttributeValue(XMLString value,
+ XMLString nonNormalizedValue,
+ String atName,
+ boolean checkEntities,String eleName)
+ throws IOException, XNIException
+ {
+ // quote
+ int quote = fEntityScanner.peekChar();
+ if (quote != '\'' && quote != '"') {
+ reportFatalError("OpenQuoteExpected", new Object[]{eleName,atName});
+ }
+
+ fEntityScanner.scanChar();
+ int entityDepth = fEntityDepth;
+
+ int c = fEntityScanner.scanLiteral(quote, value);
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** scanLiteral -> \""
+ + value.toString() + "\"");
+ }
+
+ int fromIndex = 0;
+ if (c == quote && (fromIndex = isUnchangedByNormalization(value)) == -1) {
+ /** Both the non-normalized and normalized attribute values are equal. **/
+ nonNormalizedValue.setValues(value);
+ int cquote = fEntityScanner.scanChar();
+ if (cquote != quote) {
+ reportFatalError("CloseQuoteExpected", new Object[]{eleName,atName});
+ }
+ return true;
+ }
+ fStringBuffer2.clear();
+ fStringBuffer2.append(value);
+ normalizeWhitespace(value, fromIndex);
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** normalizeWhitespace -> \""
+ + value.toString() + "\"");
+ }
+ if (c != quote) {
+ fScanningAttribute = true;
+ fStringBuffer.clear();
+ do {
+ fStringBuffer.append(value);
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** value2: \""
+ + fStringBuffer.toString() + "\"");
+ }
+ if (c == '&') {
+ fEntityScanner.skipChar('&');
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append('&');
+ }
+ if (fEntityScanner.skipChar('#')) {
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append('#');
+ }
+ int ch = scanCharReferenceValue(fStringBuffer, fStringBuffer2);
+ if (ch != -1) {
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** value3: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ }
+ else {
+ String entityName = fEntityScanner.scanName();
+ if (entityName == null) {
+ reportFatalError("NameRequiredInReference", null);
+ }
+ else if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append(entityName);
+ }
+ if (!fEntityScanner.skipChar(';')) {
+ reportFatalError("SemicolonRequiredInReference",
+ new Object []{entityName});
+ }
+ else if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append(';');
+ }
+ if (entityName == fAmpSymbol) {
+ fStringBuffer.append('&');
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** value5: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ else if (entityName == fAposSymbol) {
+ fStringBuffer.append('\'');
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** value7: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ else if (entityName == fLtSymbol) {
+ fStringBuffer.append('<');
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** value9: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ else if (entityName == fGtSymbol) {
+ fStringBuffer.append('>');
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** valueB: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ else if (entityName == fQuotSymbol) {
+ fStringBuffer.append('"');
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** valueD: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ else {
+ if (fEntityManager.isExternalEntity(entityName)) {
+ reportFatalError("ReferenceToExternalEntity",
+ new Object[] { entityName });
+ }
+ else {
+ if (!fEntityManager.isDeclaredEntity(entityName)) {
+ //WFC & VC: Entity Declared
+ if (checkEntities) {
+ if (fValidation) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "EntityNotDeclared",
+ new Object[]{entityName},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ else {
+ reportFatalError("EntityNotDeclared",
+ new Object[]{entityName});
+ }
+ }
+ fEntityManager.startEntity(entityName, true);
+ }
+ }
+ }
+ }
+ else if (c == '<') {
+ reportFatalError("LessthanInAttValue",
+ new Object[] { eleName, atName });
+ fEntityScanner.scanChar();
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append((char)c);
+ }
+ }
+ else if (c == '%' || c == ']') {
+ fEntityScanner.scanChar();
+ fStringBuffer.append((char)c);
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append((char)c);
+ }
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** valueF: \""
+ + fStringBuffer.toString() + "\"");
+ }
+ }
+ else if (c == '\n' || c == '\r') {
+ fEntityScanner.scanChar();
+ fStringBuffer.append(' ');
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append('\n');
+ }
+ }
+ else if (c != -1 && XMLChar.isHighSurrogate(c)) {
+ fStringBuffer3.clear();
+ if (scanSurrogates(fStringBuffer3)) {
+ fStringBuffer.append(fStringBuffer3);
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append(fStringBuffer3);
+ }
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** valueI: \""
+ + fStringBuffer.toString()
+ + "\"");
+ }
+ }
+ }
+ else if (c != -1 && isInvalidLiteral(c)) {
+ reportFatalError("InvalidCharInAttValue",
+ new Object[] {eleName, atName, Integer.toString(c, 16)});
+ fEntityScanner.scanChar();
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append((char)c);
+ }
+ }
+ c = fEntityScanner.scanLiteral(quote, value);
+ if (entityDepth == fEntityDepth) {
+ fStringBuffer2.append(value);
+ }
+ normalizeWhitespace(value);
+ } while (c != quote || entityDepth != fEntityDepth);
+ fStringBuffer.append(value);
+ if (DEBUG_ATTR_NORMALIZATION) {
+ System.out.println("** valueN: \""
+ + fStringBuffer.toString() + "\"");
+ }
+ value.setValues(fStringBuffer);
+ fScanningAttribute = false;
+ }
+ nonNormalizedValue.setValues(fStringBuffer2);
+
+ // quote
+ int cquote = fEntityScanner.scanChar();
+ if (cquote != quote) {
+ reportFatalError("CloseQuoteExpected", new Object[]{eleName,atName});
+ }
+ return nonNormalizedValue.equals(value.ch, value.offset, value.length);
+
+ } // scanAttributeValue()
+
+
+ /**
+ * Scans External ID and return the public and system IDs.
+ *
+ * @param identifiers An array of size 2 to return the system id,
+ * and public id (in that order).
+ * @param optionalSystemId Specifies whether the system id is optional.
+ *
+ * Note: This method uses fString and fStringBuffer,
+ * anything in them at the time of calling is lost.
+ */
+ protected void scanExternalID(String[] identifiers,
+ boolean optionalSystemId)
+ throws IOException, XNIException {
+
+ String systemId = null;
+ String publicId = null;
+ if (fEntityScanner.skipString("PUBLIC")) {
+ if (!fEntityScanner.skipSpaces()) {
+ reportFatalError("SpaceRequiredAfterPUBLIC", null);
+ }
+ scanPubidLiteral(fString);
+ publicId = fString.toString();
+
+ if (!fEntityScanner.skipSpaces() && !optionalSystemId) {
+ reportFatalError("SpaceRequiredBetweenPublicAndSystem", null);
+ }
+ }
+
+ if (publicId != null || fEntityScanner.skipString("SYSTEM")) {
+ if (publicId == null && !fEntityScanner.skipSpaces()) {
+ reportFatalError("SpaceRequiredAfterSYSTEM", null);
+ }
+ int quote = fEntityScanner.peekChar();
+ if (quote != '\'' && quote != '"') {
+ if (publicId != null && optionalSystemId) {
+ // looks like we don't have any system id
+ // simply return the public id
+ identifiers[0] = null;
+ identifiers[1] = publicId;
+ return;
+ }
+ reportFatalError("QuoteRequiredInSystemID", null);
+ }
+ fEntityScanner.scanChar();
+ XMLString ident = fString;
+ if (fEntityScanner.scanLiteral(quote, ident) != quote) {
+ fStringBuffer.clear();
+ do {
+ fStringBuffer.append(ident);
+ int c = fEntityScanner.peekChar();
+ if (XMLChar.isMarkup(c) || c == ']') {
+ fStringBuffer.append((char)fEntityScanner.scanChar());
+ }
+ else if (XMLChar.isHighSurrogate(c)) {
+ scanSurrogates(fStringBuffer);
+ }
+ else if (isInvalidLiteral(c)) {
+ reportFatalError("InvalidCharInSystemID",
+ new Object[] { Integer.toHexString(c) });
+ fEntityScanner.scanChar();
+ }
+ } while (fEntityScanner.scanLiteral(quote, ident) != quote);
+ fStringBuffer.append(ident);
+ ident = fStringBuffer;
+ }
+ systemId = ident.toString();
+ if (!fEntityScanner.skipChar(quote)) {
+ reportFatalError("SystemIDUnterminated", null);
+ }
+ }
+
+ // store result in array
+ identifiers[0] = systemId;
+ identifiers[1] = publicId;
+ }
+
+
+ /**
+ * Scans public ID literal.
+ *
+ * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
+ * [13] PubidChar::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
+ *
+ * The returned string is normalized according to the following rule,
+ * from http://www.w3.org/TR/REC-xml#dt-pubid:
+ *
+ * Before a match is attempted, all strings of white space in the public
+ * identifier must be normalized to single space characters (#x20), and
+ * leading and trailing white space must be removed.
+ *
+ * @param literal The string to fill in with the public ID literal.
+ * @return True on success.
+ *
+ * Note: This method uses fStringBuffer, anything in it at
+ * the time of calling is lost.
+ */
+ protected boolean scanPubidLiteral(XMLString literal)
+ throws IOException, XNIException
+ {
+ int quote = fEntityScanner.scanChar();
+ if (quote != '\'' && quote != '"') {
+ reportFatalError("QuoteRequiredInPublicID", null);
+ return false;
+ }
+
+ fStringBuffer.clear();
+ // skip leading whitespace
+ boolean skipSpace = true;
+ boolean dataok = true;
+ while (true) {
+ int c = fEntityScanner.scanChar();
+ if (c == ' ' || c == '\n' || c == '\r') {
+ if (!skipSpace) {
+ // take the first whitespace as a space and skip the others
+ fStringBuffer.append(' ');
+ skipSpace = true;
+ }
+ }
+ else if (c == quote) {
+ if (skipSpace) {
+ // if we finished on a space let's trim it
+ fStringBuffer.length--;
+ }
+ literal.setValues(fStringBuffer);
+ break;
+ }
+ else if (XMLChar.isPubid(c)) {
+ fStringBuffer.append((char)c);
+ skipSpace = false;
+ }
+ else if (c == -1) {
+ reportFatalError("PublicIDUnterminated", null);
+ return false;
+ }
+ else {
+ dataok = false;
+ reportFatalError("InvalidCharInPublicID",
+ new Object[]{Integer.toHexString(c)});
+ }
+ }
+ return dataok;
+ }
+
+
+ /**
+ * Normalize whitespace in an XMLString converting all whitespace
+ * characters to space characters.
+ */
+ protected void normalizeWhitespace(XMLString value) {
+ int end = value.offset + value.length;
+ for (int i = value.offset; i < end; ++i) {
+ int c = value.ch[i];
+ // Performance: For XML 1.0 documents take advantage of
+ // the fact that the only legal characters below 0x20
+ // are 0x09 (TAB), 0x0A (LF) and 0x0D (CR). Since we've
+ // already determined the well-formedness of these
+ // characters it is sufficient (and safe) to check
+ // against 0x20. -- mrglavas
+ if (c < 0x20) {
+ value.ch[i] = ' ';
+ }
+ }
+ }
+
+ /**
+ * Normalize whitespace in an XMLString converting all whitespace
+ * characters to space characters.
+ */
+ protected void normalizeWhitespace(XMLString value, int fromIndex) {
+ int end = value.offset + value.length;
+ for (int i = value.offset + fromIndex; i < end; ++i) {
+ int c = value.ch[i];
+ // Performance: For XML 1.0 documents take advantage of
+ // the fact that the only legal characters below 0x20
+ // are 0x09 (TAB), 0x0A (LF) and 0x0D (CR). Since we've
+ // already determined the well-formedness of these
+ // characters it is sufficient (and safe) to check
+ // against 0x20. -- mrglavas
+ if (c < 0x20) {
+ value.ch[i] = ' ';
+ }
+ }
+ }
+
+ /**
+ * Checks whether this string would be unchanged by normalization.
+ *
+ * @return -1 if the value would be unchanged by normalization,
+ * otherwise the index of the first whitespace character which
+ * would be transformed.
+ */
+ protected int isUnchangedByNormalization(XMLString value) {
+ int end = value.offset + value.length;
+ for (int i = value.offset; i < end; ++i) {
+ int c = value.ch[i];
+ // Performance: For XML 1.0 documents take advantage of
+ // the fact that the only legal characters below 0x20
+ // are 0x09 (TAB), 0x0A (LF) and 0x0D (CR). Since we've
+ // already determined the well-formedness of these
+ // characters it is sufficient (and safe) to check
+ // against 0x20. -- mrglavas
+ if (c < 0x20) {
+ return i - value.offset;
+ }
+ }
+ return -1;
+ }
+
+ //
+ // XMLEntityHandler methods
+ //
+
+ /**
+ * This method notifies of the start of an entity. The document entity
+ * has the pseudo-name of "[xml]" the DTD has the pseudo-name of "[dtd]"
+ * parameter entity names start with '%'; and general entities are just
+ * specified by their name.
+ *
+ * @param name The name of the entity.
+ * @param identifier The resource identifier.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal entities or a document entity that is
+ * parsed from a java.io.Reader).
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startEntity(String name,
+ XMLResourceIdentifier identifier,
+ String encoding, Augmentations augs) throws XNIException {
+
+ // keep track of the entity depth
+ fEntityDepth++;
+ // must reset entity scanner
+ fEntityScanner = fEntityManager.getEntityScanner();
+
+ } // startEntity(String,XMLResourceIdentifier,String)
+
+ /**
+ * This method notifies the end of an entity. The document entity has
+ * the pseudo-name of "[xml]" the DTD has the pseudo-name of "[dtd]"
+ * parameter entity names start with '%'; and general entities are just
+ * specified by their name.
+ *
+ * @param name The name of the entity.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endEntity(String name, Augmentations augs) throws XNIException {
+
+ // keep track of the entity depth
+ fEntityDepth--;
+
+ } // endEntity(String)
+
+ /**
+ * Scans a character reference and append the corresponding chars to the
+ * specified buffer.
+ *
+ *
+ *
+ * [66] CharRef ::= '' [0-9]+ ';' | '' [0-9a-fA-F]+ ';'
+ *
+ *
+ * Note: This method uses fStringBuffer, anything in it
+ * at the time of calling is lost.
+ *
+ * @param buf the character buffer to append chars to
+ * @param buf2 the character buffer to append non-normalized chars to
+ *
+ * @return the character value or (-1) on conversion failure
+ */
+ protected int scanCharReferenceValue(XMLStringBuffer buf, XMLStringBuffer buf2)
+ throws IOException, XNIException {
+
+ // scan hexadecimal value
+ boolean hex = false;
+ if (fEntityScanner.skipChar('x')) {
+ if (buf2 != null) { buf2.append('x'); }
+ hex = true;
+ fStringBuffer3.clear();
+ boolean digit = true;
+
+ int c = fEntityScanner.peekChar();
+ digit = (c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F');
+ if (digit) {
+ if (buf2 != null) { buf2.append((char)c); }
+ fEntityScanner.scanChar();
+ fStringBuffer3.append((char)c);
+
+ do {
+ c = fEntityScanner.peekChar();
+ digit = (c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F');
+ if (digit) {
+ if (buf2 != null) { buf2.append((char)c); }
+ fEntityScanner.scanChar();
+ fStringBuffer3.append((char)c);
+ }
+ } while (digit);
+ }
+ else {
+ reportFatalError("HexdigitRequiredInCharRef", null);
+ }
+ }
+
+ // scan decimal value
+ else {
+ fStringBuffer3.clear();
+ boolean digit = true;
+
+ int c = fEntityScanner.peekChar();
+ digit = c >= '0' && c <= '9';
+ if (digit) {
+ if (buf2 != null) { buf2.append((char)c); }
+ fEntityScanner.scanChar();
+ fStringBuffer3.append((char)c);
+
+ do {
+ c = fEntityScanner.peekChar();
+ digit = c >= '0' && c <= '9';
+ if (digit) {
+ if (buf2 != null) { buf2.append((char)c); }
+ fEntityScanner.scanChar();
+ fStringBuffer3.append((char)c);
+ }
+ } while (digit);
+ }
+ else {
+ reportFatalError("DigitRequiredInCharRef", null);
+ }
+ }
+
+ // end
+ if (!fEntityScanner.skipChar(';')) {
+ reportFatalError("SemicolonRequiredInCharRef", null);
+ }
+ if (buf2 != null) { buf2.append(';'); }
+
+ // convert string to number
+ int value = -1;
+ try {
+ value = Integer.parseInt(fStringBuffer3.toString(),
+ hex ? 16 : 10);
+
+ // character reference must be a valid XML character
+ if (isInvalid(value)) {
+ StringBuffer errorBuf = new StringBuffer(fStringBuffer3.length + 1);
+ if (hex) errorBuf.append('x');
+ errorBuf.append(fStringBuffer3.ch, fStringBuffer3.offset, fStringBuffer3.length);
+ reportFatalError("InvalidCharRef",
+ new Object[]{errorBuf.toString()});
+ }
+ }
+ catch (NumberFormatException e) {
+ // Conversion failed, let -1 value drop through.
+ // If we end up here, the character reference was invalid.
+ StringBuffer errorBuf = new StringBuffer(fStringBuffer3.length + 1);
+ if (hex) errorBuf.append('x');
+ errorBuf.append(fStringBuffer3.ch, fStringBuffer3.offset, fStringBuffer3.length);
+ reportFatalError("InvalidCharRef",
+ new Object[]{errorBuf.toString()});
+ }
+
+ // append corresponding chars to the given buffer
+ if (!XMLChar.isSupplemental(value)) {
+ buf.append((char) value);
+ }
+ else {
+ // character is supplemental, split it into surrogate chars
+ buf.append(XMLChar.highSurrogate(value));
+ buf.append(XMLChar.lowSurrogate(value));
+ }
+
+ // char refs notification code
+ if (fNotifyCharRefs && value != -1) {
+ String literal = "#" + (hex ? "x" : "") + fStringBuffer3.toString();
+ if (!fScanningAttribute) {
+ fCharRefLiteral = literal;
+ }
+ }
+
+ return value;
+ }
+
+ // returns true if the given character is not
+ // valid with respect to the version of
+ // XML understood by this scanner.
+ protected boolean isInvalid(int value) {
+ return (XMLChar.isInvalid(value));
+ } // isInvalid(int): boolean
+
+ // returns true if the given character is not
+ // valid or may not be used outside a character reference
+ // with respect to the version of XML understood by this scanner.
+ protected boolean isInvalidLiteral(int value) {
+ return (XMLChar.isInvalid(value));
+ } // isInvalidLiteral(int): boolean
+
+ // returns true if the given character is
+ // a valid nameChar with respect to the version of
+ // XML understood by this scanner.
+ protected boolean isValidNameChar(int value) {
+ return (XMLChar.isName(value));
+ } // isValidNameChar(int): boolean
+
+ // returns true if the given character is
+ // a valid nameStartChar with respect to the version of
+ // XML understood by this scanner.
+ protected boolean isValidNameStartChar(int value) {
+ return (XMLChar.isNameStart(value));
+ } // isValidNameStartChar(int): boolean
+
+ // returns true if the given character is
+ // a valid NCName character with respect to the version of
+ // XML understood by this scanner.
+ protected boolean isValidNCName(int value) {
+ return (XMLChar.isNCName(value));
+ } // isValidNCName(int): boolean
+
+ // returns true if the given character is
+ // a valid high surrogate for a nameStartChar
+ // with respect to the version of XML understood
+ // by this scanner.
+ protected boolean isValidNameStartHighSurrogate(int value) {
+ return false;
+ } // isValidNameStartHighSurrogate(int): boolean
+
+ protected boolean versionSupported(String version ) {
+ return version.equals("1.0");
+ } // version Supported
+
+ // returns the error message key for unsupported
+ // versions of XML with respect to the version of
+ // XML understood by this scanner.
+ protected String getVersionNotSupportedKey () {
+ return "VersionNotSupported";
+ } // getVersionNotSupportedKey: String
+
+ /**
+ * Scans surrogates and append them to the specified buffer.
+ *
+ * Note: This assumes the current char has already been
+ * identified as a high surrogate.
+ *
+ * @param buf The StringBuffer to append the read surrogates to.
+ * @return True if it succeeded.
+ */
+ protected boolean scanSurrogates(XMLStringBuffer buf)
+ throws IOException, XNIException {
+
+ int high = fEntityScanner.scanChar();
+ int low = fEntityScanner.peekChar();
+ if (!XMLChar.isLowSurrogate(low)) {
+ reportFatalError("InvalidCharInContent",
+ new Object[] {Integer.toString(high, 16)});
+ return false;
+ }
+ fEntityScanner.scanChar();
+
+ // convert surrogates to supplemental character
+ int c = XMLChar.supplemental((char)high, (char)low);
+
+ // supplemental character must be a valid XML character
+ if (isInvalid(c)) {
+ reportFatalError("InvalidCharInContent",
+ new Object[]{Integer.toString(c, 16)});
+ return false;
+ }
+
+ // fill in the buffer
+ buf.append((char)high);
+ buf.append((char)low);
+
+ return true;
+
+ } // scanSurrogates():boolean
+
+
+ /**
+ * Convenience function used in all XML scanners.
+ */
+ protected void reportFatalError(String msgId, Object[] args)
+ throws XNIException {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ msgId, args,
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // private methods
+ private void init() {
+ fEntityScanner = null;
+ // initialize vars
+ fEntityDepth = 0;
+ fReportEntity = true;
+ fResourceIdentifier.clear();
+ }
+
+} // class XMLScanner
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/XMLVersionDetector.java b/resources/xerces2-j-src/org/apache/xerces/impl/XMLVersionDetector.java
new file mode 100644
index 0000000..e7fd538
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/XMLVersionDetector.java
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl;
+
+import java.io.CharConversionException;
+import java.io.EOFException;
+import java.io.IOException;
+
+import org.apache.xerces.impl.io.MalformedByteSequenceException;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLInputSource;
+
+/**
+ * This class scans the version of the document to determine
+ * which scanner to use: XML 1.1 or XML 1.0.
+ * The version is scanned using XML 1.1. scanner.
+ *
+ * @xerces.internal
+ *
+ * @author Neil Graham, IBM
+ * @author Elena Litani, IBM
+ * @version $Id$
+ */
+public class XMLVersionDetector {
+
+ //
+ // Constants
+ //
+
+ private static final char[] XML11_VERSION = new char[]{'1', '.', '1'};
+
+ // property identifiers
+
+ /** Property identifier: symbol table. */
+ protected static final String SYMBOL_TABLE =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
+
+ /** Property identifier: error reporter. */
+ protected static final String ERROR_REPORTER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
+
+ /** Property identifier: entity manager. */
+ protected static final String ENTITY_MANAGER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
+
+ //
+ // Data
+ //
+
+ /** Symbol: "version". */
+ protected static final String fVersionSymbol = "version".intern();
+
+ // symbol: [xml]:
+ protected static final String fXMLSymbol = "[xml]".intern();
+
+ /** Symbol table. */
+ protected SymbolTable fSymbolTable;
+
+ /** Error reporter. */
+ protected XMLErrorReporter fErrorReporter;
+
+ /** Entity manager. */
+ protected XMLEntityManager fEntityManager;
+
+ protected String fEncoding = null;
+
+ private final char [] fExpectedVersionString = {'<', '?', 'x', 'm', 'l', ' ', 'v', 'e', 'r', 's',
+ 'i', 'o', 'n', '=', ' ', ' ', ' ', ' ', ' '};
+
+ /**
+ *
+ *
+ * @param componentManager The component manager.
+ *
+ * @throws XNIException Throws exception if required features and
+ * properties cannot be found.
+ */
+ public void reset(XMLComponentManager componentManager)
+ throws XMLConfigurationException {
+
+ // Xerces properties
+ fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
+ fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
+ fEntityManager = (XMLEntityManager)componentManager.getProperty(ENTITY_MANAGER);
+ for(int i=14; i currentEntity.ch.length) {
+ //resize array; this case is hard to imagine...
+ char[] tempCh = currentEntity.ch;
+ currentEntity.ch = new char[length+currentEntity.count-currentEntity.position+1];
+ System.arraycopy(tempCh, 0, currentEntity.ch, 0, tempCh.length);
+ }
+ if(currentEntity.position < length) {
+ // have to move sensitive stuff out of the way...
+ System.arraycopy(currentEntity.ch, currentEntity.position, currentEntity.ch, length, currentEntity.count-currentEntity.position);
+ currentEntity.count += length-currentEntity.position;
+ } else {
+ // have to reintroduce some whitespace so this parses:
+ for(int i=length; iA DTD grammar that produces balanced syntax trees.
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ * @version $Id$
+ */
+final class BalancedDTDGrammar extends DTDGrammar {
+
+ //
+ // Data
+ //
+
+ /** Mixed. */
+ private boolean fMixed;
+
+ /** Stack depth */
+ private int fDepth = 0;
+
+ /** Children content model operation stack. */
+ private short [] fOpStack = null;
+
+ /** Holder for choice/sequence/leaf groups at each depth. */
+ private int [][] fGroupIndexStack;
+
+ /** Sizes of the allocated portions of each int[] in fGroupIndexStack. */
+ private int [] fGroupIndexStackSizes;
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public BalancedDTDGrammar(SymbolTable symbolTable, XMLDTDDescription desc) {
+ super(symbolTable, desc);
+ } // BalancedDTDGrammar(SymbolTable,XMLDTDDescription)
+
+ //
+ // Public methods
+ //
+
+ /**
+ * The start of a content model. Depending on the type of the content
+ * model, specific methods may be called between the call to the
+ * startContentModel method and the call to the endContentModel method.
+ *
+ * @param elementName The name of the element.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public final void startContentModel(String elementName, Augmentations augs)
+ throws XNIException {
+ fDepth = 0;
+ initializeContentModelStacks();
+ super.startContentModel(elementName, augs);
+ } // startContentModel(String)
+
+ /**
+ * A start of either a mixed or children content model. A mixed
+ * content model will immediately be followed by a call to the
+ * pcdata() method. A children content model will
+ * contain additional groups and/or elements.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see #any
+ * @see #empty
+ */
+ public final void startGroup(Augmentations augs) throws XNIException {
+ ++fDepth;
+ initializeContentModelStacks();
+ fMixed = false;
+ } // startGroup()
+
+ /**
+ * The appearance of "#PCDATA" within a group signifying a
+ * mixed content model. This method will be the first called
+ * following the content model's startGroup() .
+ *
+ *@param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see #startGroup
+ */
+ public final void pcdata(Augmentations augs) throws XNIException {
+ fMixed = true;
+ } // pcdata()
+
+ /**
+ * A referenced element in a mixed or children content model.
+ *
+ * @param elementName The name of the referenced element.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public final void element(String elementName, Augmentations augs) throws XNIException {
+ addToCurrentGroup(addUniqueLeafNode(elementName));
+ } // element(String)
+
+ /**
+ * The separator between choices or sequences of a mixed or children
+ * content model.
+ *
+ * @param separator The type of children separator.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_CHOICE
+ * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_SEQUENCE
+ */
+ public final void separator(short separator, Augmentations augs) throws XNIException {
+ if (separator == XMLDTDContentModelHandler.SEPARATOR_CHOICE) {
+ fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_CHOICE;
+ }
+ else if (separator == XMLDTDContentModelHandler.SEPARATOR_SEQUENCE) {
+ fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_SEQ;
+ }
+ } // separator(short)
+
+ /**
+ * The occurrence count for a child in a children content model or
+ * for the mixed content model group.
+ *
+ * @param occurrence The occurrence count for the last element
+ * or group.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_ONE
+ * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_MORE
+ * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ONE_OR_MORE
+ */
+ public final void occurrence(short occurrence, Augmentations augs) throws XNIException {
+ if (!fMixed) {
+ int currentIndex = fGroupIndexStackSizes[fDepth] - 1;
+ if (occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE) {
+ fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fGroupIndexStack[fDepth][currentIndex], -1);
+ }
+ else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE) {
+ fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fGroupIndexStack[fDepth][currentIndex], -1);
+ }
+ else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE) {
+ fGroupIndexStack[fDepth][currentIndex] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fGroupIndexStack[fDepth][currentIndex], -1);
+ }
+ }
+ } // occurrence(short)
+
+ /**
+ * The end of a group for mixed or children content models.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public final void endGroup(Augmentations augs) throws XNIException {
+ final int length = fGroupIndexStackSizes[fDepth];
+ final int group = length > 0 ? addContentSpecNodes(0, length - 1) : addUniqueLeafNode(null);
+ --fDepth;
+ addToCurrentGroup(group);
+ } // endGroup()
+
+ /**
+ * The end of the DTD.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public final void endDTD(Augmentations augs) throws XNIException {
+ super.endDTD(augs);
+ fOpStack = null;
+ fGroupIndexStack = null;
+ fGroupIndexStackSizes = null;
+ } // endDTD()
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * Adds the content spec to the given element declaration.
+ */
+ protected final void addContentSpecToElement(XMLElementDecl elementDecl) {
+ int contentSpec = fGroupIndexStackSizes[0] > 0 ? fGroupIndexStack[0][0] : -1;
+ setContentSpecIndex(fCurrentElementIndex, contentSpec);
+ }
+
+ //
+ // Private methods
+ //
+
+ /**
+ * Creates a subtree from the leaf nodes at the current depth.
+ */
+ private int addContentSpecNodes(int begin, int end) {
+ if (begin == end) {
+ return fGroupIndexStack[fDepth][begin];
+ }
+ final int middle = (begin + end) >>> 1;
+ return addContentSpecNode(fOpStack[fDepth],
+ addContentSpecNodes(begin, middle),
+ addContentSpecNodes(middle + 1, end));
+ } // addContentSpecNodes(int,int)
+
+ /**
+ * Initialize the stacks which temporarily hold content models.
+ */
+ private void initializeContentModelStacks() {
+ if (fOpStack == null) {
+ fOpStack = new short[8];
+ fGroupIndexStack = new int [8][];
+ fGroupIndexStackSizes = new int [8];
+ }
+ else if (fDepth == fOpStack.length) {
+ short [] newOpStack = new short[fDepth * 2];
+ System.arraycopy(fOpStack, 0, newOpStack, 0, fDepth);
+ fOpStack = newOpStack;
+ int [][] newGroupIndexStack = new int[fDepth * 2][];
+ System.arraycopy(fGroupIndexStack, 0, newGroupIndexStack, 0, fDepth);
+ fGroupIndexStack = newGroupIndexStack;
+ int [] newGroupIndexStackLengths = new int[fDepth * 2];
+ System.arraycopy(fGroupIndexStackSizes, 0, newGroupIndexStackLengths, 0, fDepth);
+ fGroupIndexStackSizes = newGroupIndexStackLengths;
+ }
+ fOpStack[fDepth] = -1;
+ fGroupIndexStackSizes[fDepth] = 0;
+ } // initializeContentModelStacks()
+
+ /**
+ * Add XMLContentSpec to the current group.
+ *
+ * @param contentSpec handle to the XMLContentSpec to add to the current group
+ */
+ private void addToCurrentGroup(int contentSpec) {
+ int [] currentGroup = fGroupIndexStack[fDepth];
+ int length = fGroupIndexStackSizes[fDepth]++;
+ if (currentGroup == null) {
+ currentGroup = new int[8];
+ fGroupIndexStack[fDepth] = currentGroup;
+ }
+ else if (length == currentGroup.length) {
+ int [] newGroup = new int[currentGroup.length * 2];
+ System.arraycopy(currentGroup, 0, newGroup, 0, currentGroup.length);
+ currentGroup = newGroup;
+ fGroupIndexStack[fDepth] = currentGroup;
+ }
+ currentGroup[length] = contentSpec;
+ } // addToCurrentGroup(int)
+
+} // class BalancedDTDGrammar
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/DTDGrammar.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/DTDGrammar.java
new file mode 100644
index 0000000..a06f4d8
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/DTDGrammar.java
@@ -0,0 +1,2893 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Random;
+
+import org.apache.xerces.impl.dtd.models.CMAny;
+import org.apache.xerces.impl.dtd.models.CMBinOp;
+import org.apache.xerces.impl.dtd.models.CMLeaf;
+import org.apache.xerces.impl.dtd.models.CMNode;
+import org.apache.xerces.impl.dtd.models.CMUniOp;
+import org.apache.xerces.impl.dtd.models.ContentModelValidator;
+import org.apache.xerces.impl.dtd.models.DFAContentModel;
+import org.apache.xerces.impl.dtd.models.MixedContentModel;
+import org.apache.xerces.impl.dtd.models.SimpleContentModel;
+import org.apache.xerces.impl.dv.DatatypeValidator;
+import org.apache.xerces.impl.validation.EntityState;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLDTDContentModelHandler;
+import org.apache.xerces.xni.XMLDTDHandler;
+import org.apache.xerces.xni.XMLLocator;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.grammars.Grammar;
+import org.apache.xerces.xni.grammars.XMLGrammarDescription;
+import org.apache.xerces.xni.parser.XMLDTDContentModelSource;
+import org.apache.xerces.xni.parser.XMLDTDSource;
+
+/**
+ * A DTD grammar. This class implements the XNI handler interfaces
+ * for DTD information so that it can build the appropriate validation
+ * structures automatically from the callbacks.
+ *
+ * @xerces.internal
+ *
+ * @author Eric Ye, IBM
+ * @author Jeffrey Rodriguez, IBM
+ * @author Andy Clark, IBM
+ * @author Neil Graham, IBM
+ *
+ * @version $Id$
+ */
+public class DTDGrammar
+ implements XMLDTDHandler, XMLDTDContentModelHandler, EntityState, Grammar {
+
+ //
+ // Constants
+ //
+
+ /** Top level scope (-1). */
+ public static final int TOP_LEVEL_SCOPE = -1;
+
+ // private
+
+ /** Chunk shift (8). */
+ private static final int CHUNK_SHIFT = 8; // 2^8 = 256
+
+ /** Chunk size (1 << CHUNK_SHIFT). */
+ private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
+
+ /** Chunk mask (CHUNK_SIZE - 1). */
+ private static final int CHUNK_MASK = CHUNK_SIZE - 1;
+
+ /** Initial chunk count (1 << (10 - CHUNK_SHIFT)). */
+ private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); // 2^10 = 1k
+
+ /** List flag (0x80). */
+ private static final short LIST_FLAG = 0x80;
+
+ /** List mask (~LIST_FLAG). */
+ private static final short LIST_MASK = ~LIST_FLAG;
+
+ // debugging
+
+ /** Debug DTDGrammar. */
+ private static final boolean DEBUG = false;
+
+ //
+ // Data
+ //
+
+ protected XMLDTDSource fDTDSource = null;
+ protected XMLDTDContentModelSource fDTDContentModelSource = null;
+
+ /** Current element index. */
+ protected int fCurrentElementIndex;
+
+ /** Current attribute index. */
+ protected int fCurrentAttributeIndex;
+
+ /** fReadingExternalDTD */
+ protected boolean fReadingExternalDTD = false;
+
+ /** Symbol table. */
+ private SymbolTable fSymbolTable;
+
+ // The XMLDTDDescription with which this Grammar is associated
+ protected XMLDTDDescription fGrammarDescription = null;
+
+ // element declarations
+
+ /** Number of element declarations. */
+ private int fElementDeclCount = 0;
+
+ /** Element declaration name. */
+ private QName fElementDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
+
+ /**
+ * Element declaration type.
+ * @see XMLElementDecl
+ */
+ private short fElementDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
+
+ /**
+ * Element declaration content spec index. This index value is used
+ * to refer to the content spec information tables.
+ */
+ private int fElementDeclContentSpecIndex[][] = new int[INITIAL_CHUNK_COUNT][];
+
+ /**
+ * Element declaration content model validator. This validator is
+ * constructed from the content spec nodes.
+ */
+ private ContentModelValidator fElementDeclContentModelValidator[][] = new ContentModelValidator[INITIAL_CHUNK_COUNT][];
+
+ /** First attribute declaration of an element declaration. */
+ private int fElementDeclFirstAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
+
+ /** Last attribute declaration of an element declaration. */
+ private int fElementDeclLastAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
+
+ // attribute declarations
+
+ /** Number of attribute declarations. */
+ private int fAttributeDeclCount = 0 ;
+
+ /** Attribute declaration name. */
+ private QName fAttributeDeclName[][] = new QName[INITIAL_CHUNK_COUNT][];
+
+ // is this grammar immutable? (fully constructed and not changeable)
+ private boolean fIsImmutable = false;
+
+ /**
+ * Attribute declaration type.
+ * @see XMLAttributeDecl
+ */
+ private short fAttributeDeclType[][] = new short[INITIAL_CHUNK_COUNT][];
+
+ /** Attribute declaration enumeration values. */
+ private String[] fAttributeDeclEnumeration[][] = new String[INITIAL_CHUNK_COUNT][][];
+ private short fAttributeDeclDefaultType[][] = new short[INITIAL_CHUNK_COUNT][];
+ private DatatypeValidator fAttributeDeclDatatypeValidator[][] = new DatatypeValidator[INITIAL_CHUNK_COUNT][];
+ private String fAttributeDeclDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
+ private String fAttributeDeclNonNormalizedDefaultValue[][] = new String[INITIAL_CHUNK_COUNT][];
+ private int fAttributeDeclNextAttributeDeclIndex[][] = new int[INITIAL_CHUNK_COUNT][];
+
+ // content specs
+
+ // here saves the content spec binary trees for element decls,
+ // each element with a content model will hold a pointer which is
+ // the index of the head node of the content spec tree.
+
+ private int fContentSpecCount = 0;
+ private short fContentSpecType[][] = new short[INITIAL_CHUNK_COUNT][];
+ private Object fContentSpecValue[][] = new Object[INITIAL_CHUNK_COUNT][];
+ private Object fContentSpecOtherValue[][] = new Object[INITIAL_CHUNK_COUNT][];
+
+ // entities
+
+ private int fEntityCount = 0;
+ private String fEntityName[][] = new String[INITIAL_CHUNK_COUNT][];
+ private String[][] fEntityValue = new String[INITIAL_CHUNK_COUNT][];
+ private String[][] fEntityPublicId = new String[INITIAL_CHUNK_COUNT][];
+ private String[][] fEntitySystemId = new String[INITIAL_CHUNK_COUNT][];
+ private String[][] fEntityBaseSystemId = new String[INITIAL_CHUNK_COUNT][];
+ private String[][] fEntityNotation = new String[INITIAL_CHUNK_COUNT][];
+ private byte[][] fEntityIsPE = new byte[INITIAL_CHUNK_COUNT][];
+ private byte[][] fEntityInExternal = new byte[INITIAL_CHUNK_COUNT][];
+
+ // notations
+
+ private int fNotationCount = 0;
+ private String fNotationName[][] = new String[INITIAL_CHUNK_COUNT][];
+ private String[][] fNotationPublicId = new String[INITIAL_CHUNK_COUNT][];
+ private String[][] fNotationSystemId = new String[INITIAL_CHUNK_COUNT][];
+ private String[][] fNotationBaseSystemId = new String[INITIAL_CHUNK_COUNT][];
+
+ // other information
+
+ /** Element index mapping table. */
+ private QNameHashtable fElementIndexMap = new QNameHashtable();
+
+ /** Entity index mapping table. */
+ private QNameHashtable fEntityIndexMap = new QNameHashtable();
+
+ /** Notation index mapping table. */
+ private QNameHashtable fNotationIndexMap = new QNameHashtable();
+
+ // temp variables
+
+ /** Mixed. */
+ private boolean fMixed;
+
+ /** Temporary qualified name. */
+ private final QName fQName = new QName();
+
+ /** Temporary qualified name. */
+ private final QName fQName2 = new QName();
+
+ /** Temporary Attribute decl. */
+ protected final XMLAttributeDecl fAttributeDecl = new XMLAttributeDecl();
+
+ // for buildSyntaxTree method
+
+ private int fLeafCount = 0;
+ private int fEpsilonIndex = -1;
+
+ /** Element declaration. */
+ private XMLElementDecl fElementDecl = new XMLElementDecl();
+
+ /** Entity declaration. */
+ private XMLEntityDecl fEntityDecl = new XMLEntityDecl();
+
+ /** Simple type. */
+ private XMLSimpleType fSimpleType = new XMLSimpleType();
+
+ /** Content spec node. */
+ private XMLContentSpec fContentSpec = new XMLContentSpec();
+
+ /** table of XMLElementDecl */
+ Hashtable fElementDeclTab = new Hashtable();
+
+ /** Children content model operation stack. */
+ private short[] fOpStack = null;
+
+ /** Children content model index stack. */
+ private int[] fNodeIndexStack = null;
+
+ /** Children content model previous node index stack. */
+ private int[] fPrevNodeIndexStack = null;
+
+ /** Stack depth */
+ private int fDepth = 0;
+
+ /** Entity stack. */
+ private boolean[] fPEntityStack = new boolean[4];
+ private int fPEDepth = 0;
+
+ // additional fields(columns) for the element Decl pool in the Grammar
+
+ /** flag if the elementDecl is External. */
+ private int fElementDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][];
+
+
+ // additional fields(columns) for the attribute Decl pool in the Grammar
+
+ /** flag if the AttributeDecl is External. */
+ private int fAttributeDeclIsExternal[][] = new int[INITIAL_CHUNK_COUNT][];
+
+ // for mixedElement method
+
+ int valueIndex = -1;
+ int prevNodeIndex = -1;
+ int nodeIndex = -1;
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public DTDGrammar(SymbolTable symbolTable, XMLDTDDescription desc) {
+ fSymbolTable = symbolTable;
+ fGrammarDescription = desc;
+ } // (SymbolTable)
+
+ // Grammar methods
+
+ // return the XMLDTDDescription object with which this is associated
+ public XMLGrammarDescription getGrammarDescription() {
+ return fGrammarDescription;
+ } // getGrammarDescription(): XMLGrammarDescription
+
+ //
+ // Public methods
+ //
+
+ /**
+ * Returns true if the specified element declaration is external.
+ *
+ * @param elementDeclIndex The element declaration index.
+ */
+ public boolean getElementDeclIsExternal(int elementDeclIndex) {
+
+ if (elementDeclIndex < 0) {
+ return false;
+ }
+
+ int chunk = elementDeclIndex >> CHUNK_SHIFT;
+ int index = elementDeclIndex & CHUNK_MASK;
+ return (fElementDeclIsExternal[chunk][index] != 0);
+
+ } // getElementDeclIsExternal(int):boolean
+
+ /**
+ * Returns true if the specified attribute declaration is external.
+ *
+ * @param attributeDeclIndex Attribute declaration index.
+ */
+ public boolean getAttributeDeclIsExternal(int attributeDeclIndex) {
+
+ if (attributeDeclIndex < 0) {
+ return false;
+ }
+
+ int chunk = attributeDeclIndex >> CHUNK_SHIFT;
+ int index = attributeDeclIndex & CHUNK_MASK;
+ return (fAttributeDeclIsExternal[chunk][index] != 0);
+ }
+
+ public int getAttributeDeclIndex(int elementDeclIndex, String attributeDeclName) {
+ if (elementDeclIndex == -1) {
+ return -1;
+ }
+ int attDefIndex = getFirstAttributeDeclIndex(elementDeclIndex);
+ while (attDefIndex != -1) {
+ getAttributeDecl(attDefIndex, fAttributeDecl);
+
+ if (fAttributeDecl.name.rawname == attributeDeclName
+ || attributeDeclName.equals(fAttributeDecl.name.rawname) ) {
+ return attDefIndex;
+ }
+ attDefIndex = getNextAttributeDeclIndex(attDefIndex);
+ }
+ return -1;
+ } // getAttributeDeclIndex (int,QName)
+
+ //
+ // XMLDTDHandler methods
+ //
+
+ /**
+ * The start of the DTD.
+ *
+ * @param locator The document locator, or null if the document
+ * location cannot be reported during the parsing of
+ * the document DTD. However, it is strongly
+ * recommended that a locator be supplied that can
+ * at least report the base system identifier of the
+ * DTD.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException {
+ //Initialize stack
+ fOpStack = null;
+ fNodeIndexStack = null;
+ fPrevNodeIndexStack = null;
+ } // startDTD(XMLLocator)
+
+ /**
+ * This method notifies of the start of an entity. The DTD has the
+ * pseudo-name of "[dtd]" and parameter entity names start with '%'.
+ *
+ * Note: Since the DTD is an entity, the handler
+ * will be notified of the start of the DTD entity by calling the
+ * startParameterEntity method with the entity name "[dtd]" before calling
+ * the startDTD method.
+ *
+ * @param name The name of the parameter entity.
+ * @param identifier The resource identifier.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal parameter entities).
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startParameterEntity(String name,
+ XMLResourceIdentifier identifier,
+ String encoding,
+ Augmentations augs) throws XNIException {
+
+ // keep track of this entity before fEntityDepth is increased
+ if (fPEDepth == fPEntityStack.length) {
+ boolean[] entityarray = new boolean[fPEntityStack.length * 2];
+ System.arraycopy(fPEntityStack, 0, entityarray, 0, fPEntityStack.length);
+ fPEntityStack = entityarray;
+ }
+ fPEntityStack[fPEDepth] = fReadingExternalDTD;
+ fPEDepth++;
+
+ } // startParameterEntity(String,XMLResourceIdentifier,String,Augmentations)
+
+ /**
+ * The start of the DTD external subset.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startExternalSubset(XMLResourceIdentifier identifier,
+ Augmentations augs) throws XNIException {
+ fReadingExternalDTD = true;
+ } // startExternalSubset(Augmentations)
+
+ /**
+ * This method notifies the end of an entity. The DTD has the pseudo-name
+ * of "[dtd]" and parameter entity names start with '%'.
+ *
+ * Note: Since the DTD is an entity, the handler
+ * will be notified of the end of the DTD entity by calling the
+ * endEntity method with the entity name "[dtd]" after calling
+ * the endDTD method.
+ *
+ * @param name The name of the entity.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endParameterEntity(String name, Augmentations augs) throws XNIException {
+
+ fPEDepth--;
+ fReadingExternalDTD = fPEntityStack[fPEDepth];
+
+ } // endParameterEntity(String,Augmentations)
+
+ /**
+ * The end of the DTD external subset.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endExternalSubset(Augmentations augs) throws XNIException {
+ fReadingExternalDTD = false;
+ } // endExternalSubset(Augmentations)
+
+ /**
+ * An element declaration.
+ *
+ * @param name The name of the element.
+ * @param contentModel The element content model.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void elementDecl(String name, String contentModel, Augmentations augs)
+ throws XNIException {
+
+ XMLElementDecl tmpElementDecl = (XMLElementDecl) fElementDeclTab.get(name) ;
+
+ // check if it is already defined
+ if ( tmpElementDecl != null ) {
+ if (tmpElementDecl.type == -1) {
+ fCurrentElementIndex = getElementDeclIndex(name);
+ }
+ else {
+ // duplicate element, ignored.
+ return;
+ }
+ }
+ else {
+ fCurrentElementIndex = createElementDecl();//create element decl
+ }
+
+ XMLElementDecl elementDecl = new XMLElementDecl();
+
+ fQName.setValues(null, name, name, null);
+
+ elementDecl.name.setValues(fQName);
+
+ elementDecl.contentModelValidator = null;
+ elementDecl.scope= -1;
+ if (contentModel.equals("EMPTY")) {
+ elementDecl.type = XMLElementDecl.TYPE_EMPTY;
+ }
+ else if (contentModel.equals("ANY")) {
+ elementDecl.type = XMLElementDecl.TYPE_ANY;
+ }
+ else if (contentModel.startsWith("(") ) {
+ if (contentModel.indexOf("#PCDATA") > 0 ) {
+ elementDecl.type = XMLElementDecl.TYPE_MIXED;
+ }
+ else {
+ elementDecl.type = XMLElementDecl.TYPE_CHILDREN;
+ }
+ }
+
+
+ //add(or set) this elementDecl to the local cache
+ this.fElementDeclTab.put(name, elementDecl );
+
+ fElementDecl = elementDecl;
+ addContentSpecToElement(elementDecl);
+
+ if ( DEBUG ) {
+ System.out.println( "name = " + fElementDecl.name.localpart );
+ System.out.println( "Type = " + fElementDecl.type );
+ }
+
+ setElementDecl(fCurrentElementIndex, fElementDecl );//set internal structure
+
+ int chunk = fCurrentElementIndex >> CHUNK_SHIFT;
+ int index = fCurrentElementIndex & CHUNK_MASK;
+ ensureElementDeclCapacity(chunk);
+ fElementDeclIsExternal[chunk][index] = (fReadingExternalDTD || fPEDepth > 0) ? 1 : 0;
+
+ } // elementDecl(String,String)
+
+ /**
+ * An attribute declaration.
+ *
+ * @param elementName The name of the element that this attribute
+ * is associated with.
+ * @param attributeName The name of the attribute.
+ * @param type The attribute type. This value will be one of
+ * the following: "CDATA", "ENTITY", "ENTITIES",
+ * "ENUMERATION", "ID", "IDREF", "IDREFS",
+ * "NMTOKEN", "NMTOKENS", or "NOTATION".
+ * @param enumeration If the type has the value "ENUMERATION", this
+ * array holds the allowed attribute values;
+ * otherwise, this array is null.
+ * @param defaultType The attribute default type. This value will be
+ * one of the following: "#FIXED", "#IMPLIED",
+ * "#REQUIRED", or null.
+ * @param defaultValue The attribute default value, or null if no
+ * default value is specified.
+ * @param nonNormalizedDefaultValue The attribute default value with no normalization
+ * performed, or null if no default value is specified.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void attributeDecl(String elementName, String attributeName,
+ String type, String[] enumeration,
+ String defaultType, XMLString defaultValue,
+ XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
+
+ if ( this.fElementDeclTab.containsKey( (String) elementName) ) {
+ //if ElementDecl has already being created in the Grammar then remove from table,
+ //this.fElementDeclTab.remove( (String) elementName );
+ }
+ // then it is forward reference to a element decl, create the elementDecl first.
+ else {
+ fCurrentElementIndex = createElementDecl();//create element decl
+
+ XMLElementDecl elementDecl = new XMLElementDecl();
+ elementDecl.name.setValues(null, elementName, elementName, null);
+
+ elementDecl.scope= -1;
+
+ //add(or set) this elementDecl to the local cache
+ this.fElementDeclTab.put(elementName, elementDecl );
+
+ //set internal structure
+ setElementDecl(fCurrentElementIndex, elementDecl );
+ }
+
+ //Get Grammar index to grammar array
+ int elementIndex = getElementDeclIndex(elementName);
+
+ //return, when more than one definition is provided for the same attribute of given element type
+ //only the first declaration is binding and later declarations are ignored
+ if (getAttributeDeclIndex(elementIndex, attributeName) != -1) {
+ return;
+ }
+
+ fCurrentAttributeIndex = createAttributeDecl();// Create current Attribute Decl
+
+ fSimpleType.clear();
+ if ( defaultType != null ) {
+ if ( defaultType.equals( "#FIXED") ) {
+ fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_FIXED;
+ } else if ( defaultType.equals( "#IMPLIED") ) {
+ fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
+ } else if ( defaultType.equals( "#REQUIRED") ) {
+ fSimpleType.defaultType = XMLSimpleType.DEFAULT_TYPE_REQUIRED;
+ }
+ }
+ if ( DEBUG ) {
+ System.out.println("defaultvalue = " + defaultValue.toString() );
+ }
+ fSimpleType.defaultValue = defaultValue!=null ? defaultValue.toString() : null;
+ fSimpleType.nonNormalizedDefaultValue = nonNormalizedDefaultValue!=null ? nonNormalizedDefaultValue.toString() : null;
+ fSimpleType.enumeration = enumeration;
+
+ if (type.equals("CDATA")) {
+ fSimpleType.type = XMLSimpleType.TYPE_CDATA;
+ }
+ else if ( type.equals("ID") ) {
+ fSimpleType.type = XMLSimpleType.TYPE_ID;
+ }
+ else if ( type.startsWith("IDREF") ) {
+ fSimpleType.type = XMLSimpleType.TYPE_IDREF;
+ if (type.indexOf("S") > 0) {
+ fSimpleType.list = true;
+ }
+ }
+ else if (type.equals("ENTITIES")) {
+ fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
+ fSimpleType.list = true;
+ }
+ else if (type.equals("ENTITY")) {
+ fSimpleType.type = XMLSimpleType.TYPE_ENTITY;
+ }
+ else if (type.equals("NMTOKENS")) {
+ fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
+ fSimpleType.list = true;
+ }
+ else if (type.equals("NMTOKEN")) {
+ fSimpleType.type = XMLSimpleType.TYPE_NMTOKEN;
+ }
+ else if (type.startsWith("NOTATION") ) {
+ fSimpleType.type = XMLSimpleType.TYPE_NOTATION;
+ }
+ else if (type.startsWith("ENUMERATION") ) {
+ fSimpleType.type = XMLSimpleType.TYPE_ENUMERATION;
+ }
+ else {
+ // REVISIT: Report error message. -Ac
+ System.err.println("!!! unknown attribute type "+type);
+ }
+ // REVISIT: The datatype should be stored with the attribute value
+ // and not special-cased in the XMLValidator. -Ac
+ //fSimpleType.datatypeValidator = fDatatypeValidatorFactory.createDatatypeValidator(type, null, facets, fSimpleType.list);
+
+ fQName.setValues(null, attributeName, attributeName, null);
+ fAttributeDecl.setValues( fQName, fSimpleType, false );
+
+ setAttributeDecl(elementIndex, fCurrentAttributeIndex, fAttributeDecl);
+
+ int chunk = fCurrentAttributeIndex >> CHUNK_SHIFT;
+ int index = fCurrentAttributeIndex & CHUNK_MASK;
+ ensureAttributeDeclCapacity(chunk);
+ fAttributeDeclIsExternal[chunk][index] = (fReadingExternalDTD || fPEDepth > 0) ? 1 : 0;
+
+ } // attributeDecl(String,String,String,String[],String,XMLString,XMLString, Augmentations)
+
+ /**
+ * An internal entity declaration.
+ *
+ * @param name The name of the entity. Parameter entity names start with
+ * '%', whereas the name of a general entity is just the
+ * entity name.
+ * @param text The value of the entity.
+ * @param nonNormalizedText The non-normalized value of the entity. This
+ * value contains the same sequence of characters that was in
+ * the internal entity declaration, without any entity
+ * references expanded.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void internalEntityDecl(String name, XMLString text,
+ XMLString nonNormalizedText,
+ Augmentations augs) throws XNIException {
+
+ int entityIndex = getEntityDeclIndex(name);
+ if( entityIndex == -1){
+ entityIndex = createEntityDecl();
+ boolean isPE = name.startsWith("%");
+ boolean inExternal = (fReadingExternalDTD || fPEDepth > 0);
+ XMLEntityDecl entityDecl = new XMLEntityDecl();
+ entityDecl.setValues(name,null,null, null, null,
+ text.toString(), isPE, inExternal);
+
+ setEntityDecl(entityIndex, entityDecl);
+ }
+
+ } // internalEntityDecl(String,XMLString,XMLString)
+
+ /**
+ * An external entity declaration.
+ *
+ * @param name The name of the entity. Parameter entity names start
+ * with '%', whereas the name of a general entity is just
+ * the entity name.
+ * @param identifier An object containing all location information
+ * pertinent to this external entity declaration.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void externalEntityDecl(String name,
+ XMLResourceIdentifier identifier,
+ Augmentations augs) throws XNIException {
+
+ int entityIndex = getEntityDeclIndex(name);
+ if( entityIndex == -1){
+ entityIndex = createEntityDecl();
+ boolean isPE = name.startsWith("%");
+ boolean inExternal = (fReadingExternalDTD || fPEDepth > 0);
+
+ XMLEntityDecl entityDecl = new XMLEntityDecl();
+ entityDecl.setValues(name, identifier.getPublicId(), identifier.getLiteralSystemId(),
+ identifier.getBaseSystemId(),
+ null, null, isPE, inExternal);
+
+ setEntityDecl(entityIndex, entityDecl);
+ }
+ } // externalEntityDecl(String, XMLResourceIdentifier, Augmentations)
+
+ /**
+ * An unparsed entity declaration.
+ *
+ * @param name The name of the entity.
+ * @param identifier An object containing all location information
+ * pertinent to this entity.
+ * @param notation The name of the notation.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier,
+ String notation,
+ Augmentations augs) throws XNIException {
+
+ XMLEntityDecl entityDecl = new XMLEntityDecl();
+ boolean isPE = name.startsWith("%");
+ boolean inExternal = (fReadingExternalDTD || fPEDepth > 0);
+
+ entityDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(),
+ identifier.getBaseSystemId(), notation,
+ null, isPE, inExternal);
+ int entityIndex = getEntityDeclIndex(name);
+ if (entityIndex == -1) {
+ entityIndex = createEntityDecl();
+ setEntityDecl(entityIndex, entityDecl);
+ }
+
+ } // unparsedEntityDecl(String,StringXMLResourceIdentifier,Augmentations)
+
+ /**
+ * A notation declaration
+ *
+ * @param name The name of the notation.
+ * @param identifier An object containing all location information
+ * pertinent to this notation.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void notationDecl(String name, XMLResourceIdentifier identifier,
+ Augmentations augs) throws XNIException {
+
+ XMLNotationDecl notationDecl = new XMLNotationDecl();
+ notationDecl.setValues(name,identifier.getPublicId(),identifier.getLiteralSystemId(),
+ identifier.getBaseSystemId());
+ int notationIndex = getNotationDeclIndex(name);
+ if (notationIndex == -1) {
+ notationIndex = createNotationDecl();
+ setNotationDecl(notationIndex, notationDecl);
+ }
+
+ } // notationDecl(String,XMLResourceIdentifier,Augmentations)
+
+ /**
+ * The end of the DTD.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endDTD(Augmentations augs) throws XNIException {
+ fIsImmutable = true;
+ // make sure our description contains useful stuff...
+ if (fGrammarDescription.getRootName() == null) {
+ // we don't know what the root is; so use possibleRoots...
+ int chunk, index = 0;
+ String currName = null;
+ final int size = fElementDeclCount;
+ ArrayList elements = new ArrayList(size);
+ for (int i = 0; i < size; ++i) {
+ chunk = i >> CHUNK_SHIFT;
+ index = i & CHUNK_MASK;
+ currName = fElementDeclName[chunk][index].rawname;
+ elements.add(currName);
+ }
+ fGrammarDescription.setPossibleRoots(elements);
+ }
+ } // endDTD()
+
+ // sets the source of this handler
+ public void setDTDSource(XMLDTDSource source) {
+ fDTDSource = source;
+ } // setDTDSource(XMLDTDSource)
+
+ // returns the source of this handler
+ public XMLDTDSource getDTDSource() {
+ return fDTDSource;
+ } // getDTDSource(): XMLDTDSource
+
+ // no-op methods
+
+ /**
+ * Notifies of the presence of a TextDecl line in an entity. If present,
+ * this method will be called immediately following the startEntity call.
+ *
+ * Note: This method is only called for external
+ * parameter entities referenced in the DTD.
+ *
+ * @param version The XML version, or null if not specified.
+ * @param encoding The IANA encoding name of the entity.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void textDecl(String version, String encoding, Augmentations augs)
+ throws XNIException {}
+
+ /**
+ * A comment.
+ *
+ * @param text The text in the comment.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by application to signal an error.
+ */
+ public void comment(XMLString text, Augmentations augs) throws XNIException {}
+
+ /**
+ * A processing instruction. Processing instructions consist of a
+ * target name and, optionally, text data. The data is only meaningful
+ * to the application.
+ *
+ * Typically, a processing instruction's data will contain a series
+ * of pseudo-attributes. These pseudo-attributes follow the form of
+ * element attributes but are not parsed or presented
+ * to the application as anything other than text. The application is
+ * responsible for parsing the data.
+ *
+ * @param target The target.
+ * @param data The data or null if none specified.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void processingInstruction(String target, XMLString data,
+ Augmentations augs) throws XNIException {}
+
+ /**
+ * The start of an attribute list.
+ *
+ * @param elementName The name of the element that this attribute
+ * list is associated with.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startAttlist(String elementName, Augmentations augs)
+ throws XNIException {}
+
+ /**
+ * The end of an attribute list.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endAttlist(Augmentations augs) throws XNIException {}
+
+ /**
+ * The start of a conditional section.
+ *
+ * @param type The type of the conditional section. This value will
+ * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see XMLDTDHandler#CONDITIONAL_INCLUDE
+ * @see XMLDTDHandler#CONDITIONAL_IGNORE
+ */
+ public void startConditional(short type, Augmentations augs)
+ throws XNIException {}
+
+ /**
+ * Characters within an IGNORE conditional section.
+ *
+ * @param text The ignored text.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ */
+ public void ignoredCharacters(XMLString text, Augmentations augs)
+ throws XNIException {}
+
+ /**
+ * The end of a conditional section.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endConditional(Augmentations augs) throws XNIException {}
+
+ //
+ // XMLDTDContentModelHandler methods
+ //
+
+ // set content model source
+ public void setDTDContentModelSource(XMLDTDContentModelSource source) {
+ fDTDContentModelSource = source;
+ }
+
+ // get content model source
+ public XMLDTDContentModelSource getDTDContentModelSource() {
+ return fDTDContentModelSource;
+ }
+
+ /**
+ * The start of a content model. Depending on the type of the content
+ * model, specific methods may be called between the call to the
+ * startContentModel method and the call to the endContentModel method.
+ *
+ * @param elementName The name of the element.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startContentModel(String elementName, Augmentations augs)
+ throws XNIException {
+
+ XMLElementDecl elementDecl = (XMLElementDecl) this.fElementDeclTab.get( elementName);
+ if ( elementDecl != null ) {
+ fElementDecl = elementDecl;
+ }
+ fDepth = 0;
+ initializeContentModelStack();
+
+ } // startContentModel(String)
+
+ /**
+ * A start of either a mixed or children content model. A mixed
+ * content model will immediately be followed by a call to the
+ * pcdata() method. A children content model will
+ * contain additional groups and/or elements.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see #any
+ * @see #empty
+ */
+ public void startGroup(Augmentations augs) throws XNIException {
+ fDepth++;
+ initializeContentModelStack();
+ fMixed = false;
+ } // startGroup()
+
+ /**
+ * The appearance of "#PCDATA" within a group signifying a
+ * mixed content model. This method will be the first called
+ * following the content model's startGroup() .
+ *
+ *@param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see #startGroup
+ */
+ public void pcdata(Augmentations augs) throws XNIException {
+ fMixed = true;
+ } // pcdata()
+
+ /**
+ * A referenced element in a mixed or children content model.
+ *
+ * @param elementName The name of the referenced element.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void element(String elementName, Augmentations augs) throws XNIException {
+ if (fMixed) {
+ if (fNodeIndexStack[fDepth] == -1 ) {
+ fNodeIndexStack[fDepth] = addUniqueLeafNode(elementName);
+ }
+ else {
+ fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
+ fNodeIndexStack[fDepth],
+ addUniqueLeafNode(elementName));
+ }
+ }
+ else {
+ fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF, elementName);
+ }
+ } // element(String)
+
+ /**
+ * The separator between choices or sequences of a mixed or children
+ * content model.
+ *
+ * @param separator The type of children separator.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_CHOICE
+ * @see org.apache.xerces.xni.XMLDTDContentModelHandler#SEPARATOR_SEQUENCE
+ */
+ public void separator(short separator, Augmentations augs) throws XNIException {
+
+ if (!fMixed) {
+ if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_SEQ && separator == XMLDTDContentModelHandler.SEPARATOR_CHOICE ) {
+ if (fPrevNodeIndexStack[fDepth] != -1) {
+ fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]);
+ }
+ fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth];
+ fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_CHOICE;
+ } else if (fOpStack[fDepth] != XMLContentSpec.CONTENTSPECNODE_CHOICE && separator == XMLDTDContentModelHandler.SEPARATOR_SEQUENCE) {
+ if (fPrevNodeIndexStack[fDepth] != -1) {
+ fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]);
+ }
+ fPrevNodeIndexStack[fDepth] = fNodeIndexStack[fDepth];
+ fOpStack[fDepth] = XMLContentSpec.CONTENTSPECNODE_SEQ;
+ }
+ }
+
+ } // separator(short)
+
+ /**
+ * The occurrence count for a child in a children content model or
+ * for the mixed content model group.
+ *
+ * @param occurrence The occurrence count for the last element
+ * or group.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_ONE
+ * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ZERO_OR_MORE
+ * @see org.apache.xerces.xni.XMLDTDContentModelHandler#OCCURS_ONE_OR_MORE
+ */
+ public void occurrence(short occurrence, Augmentations augs) throws XNIException {
+
+ if (!fMixed) {
+ if (occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE ) {
+ fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[fDepth], -1);
+ } else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE ) {
+ fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[fDepth], -1 );
+ } else if ( occurrence == XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE) {
+ fNodeIndexStack[fDepth] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[fDepth], -1 );
+ }
+ }
+
+ } // occurrence(short)
+
+ /**
+ * The end of a group for mixed or children content models.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endGroup(Augmentations augs) throws XNIException {
+
+ if (!fMixed) {
+ if (fPrevNodeIndexStack[fDepth] != -1) {
+ fNodeIndexStack[fDepth] = addContentSpecNode(fOpStack[fDepth], fPrevNodeIndexStack[fDepth], fNodeIndexStack[fDepth]);
+ }
+ int nodeIndex = fNodeIndexStack[fDepth--];
+ fNodeIndexStack[fDepth] = nodeIndex;
+ }
+
+ } // endGroup()
+
+ // no-op methods
+
+ /**
+ * A content model of ANY.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see #empty
+ * @see #startGroup
+ */
+ public void any(Augmentations augs) throws XNIException {}
+
+ /**
+ * A content model of EMPTY.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see #any
+ * @see #startGroup
+ */
+ public void empty(Augmentations augs) throws XNIException {}
+
+ /**
+ * The end of a content model.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endContentModel(Augmentations augs) throws XNIException {}
+
+ //
+ // Grammar methods
+ //
+
+ /** Returns true if this grammar is namespace aware. */
+ public boolean isNamespaceAware() {
+ return false;
+ } // isNamespaceAware():boolean
+
+ /** Returns the symbol table. */
+ public SymbolTable getSymbolTable() {
+ return fSymbolTable;
+ } // getSymbolTable():SymbolTable
+
+ /**
+ * Returns the index of the first element declaration. This index
+ * is then used to query more information about the element declaration.
+ *
+ * @see #getNextElementDeclIndex
+ * @see #getElementDecl
+ */
+ public int getFirstElementDeclIndex() {
+ return fElementDeclCount >= 0 ? 0 : -1;
+ } // getFirstElementDeclIndex():int
+
+ /**
+ * Returns the next index of the element declaration following the
+ * specified element declaration.
+ *
+ * @param elementDeclIndex The element declaration index.
+ */
+ public int getNextElementDeclIndex(int elementDeclIndex) {
+ return elementDeclIndex < fElementDeclCount - 1
+ ? elementDeclIndex + 1 : -1;
+ } // getNextElementDeclIndex(int):int
+
+ /**
+ * getElementDeclIndex
+ *
+ * @param elementDeclName
+ *
+ * @return index of the elementDeclName in scope
+ */
+ public int getElementDeclIndex(String elementDeclName) {
+ int mapping = fElementIndexMap.get(elementDeclName);
+ //System.out.println("getElementDeclIndex("+elementDeclName+") -> "+mapping);
+ return mapping;
+ } // getElementDeclIndex(String):int
+
+ /** Returns the element decl index.
+ * @param elementDeclQName qualilfied name of the element
+ */
+ public int getElementDeclIndex(QName elementDeclQName) {
+ return getElementDeclIndex(elementDeclQName.rawname);
+ } // getElementDeclIndex(QName):int
+
+ /** make separate function for getting contentSpecType of element.
+ * we can avoid setting of the element values.
+ */
+
+ public short getContentSpecType(int elementIndex){
+ if (elementIndex < 0 || elementIndex >= fElementDeclCount) {
+ return -1 ;
+ }
+
+ int chunk = elementIndex >> CHUNK_SHIFT;
+ int index = elementIndex & CHUNK_MASK;
+
+ if(fElementDeclType[chunk][index] == -1){
+ return -1 ;
+ }
+ else{
+ return (short) (fElementDeclType[chunk][index] & LIST_MASK);
+ }
+
+ }//getContentSpecType
+
+ /**
+ * getElementDecl
+ *
+ * @param elementDeclIndex
+ * @param elementDecl The values of this structure are set by this call.
+ *
+ * @return True if find the element, False otherwise.
+ */
+ public boolean getElementDecl(int elementDeclIndex,
+ XMLElementDecl elementDecl) {
+
+ if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
+ return false;
+ }
+
+ int chunk = elementDeclIndex >> CHUNK_SHIFT;
+ int index = elementDeclIndex & CHUNK_MASK;
+
+ elementDecl.name.setValues(fElementDeclName[chunk][index]);
+
+ if (fElementDeclType[chunk][index] == -1) {
+ elementDecl.type = -1;
+ elementDecl.simpleType.list = false;
+ } else {
+ elementDecl.type = (short) (fElementDeclType[chunk][index] & LIST_MASK);
+ elementDecl.simpleType.list = (fElementDeclType[chunk][index] & LIST_FLAG) != 0;
+ }
+
+ /* Validators are null until we add that code */
+ if (elementDecl.type == XMLElementDecl.TYPE_CHILDREN || elementDecl.type == XMLElementDecl.TYPE_MIXED) {
+ elementDecl.contentModelValidator = getElementContentModelValidator(elementDeclIndex);
+ }
+
+ elementDecl.simpleType.datatypeValidator = null;
+ elementDecl.simpleType.defaultType = -1;
+ elementDecl.simpleType.defaultValue = null;
+
+ return true;
+
+ } // getElementDecl(int,XMLElementDecl):boolean
+
+ QName getElementDeclName(int elementDeclIndex) {
+ if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
+ return null;
+ }
+ int chunk = elementDeclIndex >> CHUNK_SHIFT;
+ int index = elementDeclIndex & CHUNK_MASK;
+ return fElementDeclName[chunk][index];
+ }
+
+ // REVISIT: Make this getAttributeDeclCount/getAttributeDeclAt. -Ac
+
+ /**
+ * getFirstAttributeDeclIndex
+ *
+ * @param elementDeclIndex
+ *
+ * @return index of the first attribute for element declaration elementDeclIndex
+ */
+ public int getFirstAttributeDeclIndex(int elementDeclIndex) {
+ int chunk = elementDeclIndex >> CHUNK_SHIFT;
+ int index = elementDeclIndex & CHUNK_MASK;
+
+ return fElementDeclFirstAttributeDeclIndex[chunk][index];
+ } // getFirstAttributeDeclIndex
+
+ /**
+ * getNextAttributeDeclIndex
+ *
+ * @param attributeDeclIndex
+ *
+ * @return index of the next attribute of the attribute at attributeDeclIndex
+ */
+ public int getNextAttributeDeclIndex(int attributeDeclIndex) {
+ int chunk = attributeDeclIndex >> CHUNK_SHIFT;
+ int index = attributeDeclIndex & CHUNK_MASK;
+
+ return fAttributeDeclNextAttributeDeclIndex[chunk][index];
+ } // getNextAttributeDeclIndex
+
+ /**
+ * getAttributeDecl
+ *
+ * @param attributeDeclIndex
+ * @param attributeDecl The values of this structure are set by this call.
+ *
+ * @return true if getAttributeDecl was able to fill in the value of attributeDecl
+ */
+ public boolean getAttributeDecl(int attributeDeclIndex, XMLAttributeDecl attributeDecl) {
+ if (attributeDeclIndex < 0 || attributeDeclIndex >= fAttributeDeclCount) {
+ return false;
+ }
+ int chunk = attributeDeclIndex >> CHUNK_SHIFT;
+ int index = attributeDeclIndex & CHUNK_MASK;
+
+ attributeDecl.name.setValues(fAttributeDeclName[chunk][index]);
+
+ short attributeType;
+ boolean isList;
+
+ if (fAttributeDeclType[chunk][index] == -1) {
+
+ attributeType = -1;
+ isList = false;
+ } else {
+ attributeType = (short) (fAttributeDeclType[chunk][index] & LIST_MASK);
+ isList = (fAttributeDeclType[chunk][index] & LIST_FLAG) != 0;
+ }
+ attributeDecl.simpleType.setValues(attributeType,fAttributeDeclName[chunk][index].localpart,
+ fAttributeDeclEnumeration[chunk][index],
+ isList, fAttributeDeclDefaultType[chunk][index],
+ fAttributeDeclDefaultValue[chunk][index],
+ fAttributeDeclNonNormalizedDefaultValue[chunk][index],
+ fAttributeDeclDatatypeValidator[chunk][index]);
+ return true;
+
+ } // getAttributeDecl
+
+
+ /**
+ * Returns whether the given attribute is of type CDATA or not
+ *
+ * @param elName The element name.
+ * @param atName The attribute name.
+ *
+ * @return true if the attribute is of type CDATA
+ */
+ public boolean isCDATAAttribute(QName elName, QName atName) {
+ int elDeclIdx = getElementDeclIndex(elName);
+ if (getAttributeDecl(elDeclIdx, fAttributeDecl)
+ && fAttributeDecl.simpleType.type != XMLSimpleType.TYPE_CDATA){
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * getEntityDeclIndex
+ *
+ * @param entityDeclName
+ *
+ * @return the index of the EntityDecl
+ */
+ public int getEntityDeclIndex(String entityDeclName) {
+ if (entityDeclName == null) {
+ return -1;
+ }
+
+ return fEntityIndexMap.get(entityDeclName);
+ } // getEntityDeclIndex
+
+ /**
+ * getEntityDecl
+ *
+ * @param entityDeclIndex
+ * @param entityDecl
+ *
+ * @return true if getEntityDecl was able to fill entityDecl with the contents of the entity
+ * with index entityDeclIndex
+ */
+ public boolean getEntityDecl(int entityDeclIndex, XMLEntityDecl entityDecl) {
+ if (entityDeclIndex < 0 || entityDeclIndex >= fEntityCount) {
+ return false;
+ }
+ int chunk = entityDeclIndex >> CHUNK_SHIFT;
+ int index = entityDeclIndex & CHUNK_MASK;
+
+ entityDecl.setValues(fEntityName[chunk][index],
+ fEntityPublicId[chunk][index],
+ fEntitySystemId[chunk][index],
+ fEntityBaseSystemId[chunk][index],
+ fEntityNotation[chunk][index],
+ fEntityValue[chunk][index],
+ fEntityIsPE[chunk][index] == 0 ? false : true ,
+ fEntityInExternal[chunk][index] == 0 ? false : true );
+
+ return true;
+ } // getEntityDecl
+
+ /**
+ * getNotationDeclIndex
+ *
+ * @param notationDeclName
+ *
+ * @return the index if found a notation with the name, otherwise -1.
+ */
+ public int getNotationDeclIndex(String notationDeclName) {
+ if (notationDeclName == null) {
+ return -1;
+ }
+
+ return fNotationIndexMap.get(notationDeclName);
+ } // getNotationDeclIndex
+
+ /**
+ * getNotationDecl
+ *
+ * @param notationDeclIndex
+ * @param notationDecl
+ *
+ * @return return true of getNotationDecl can fill notationDecl with information about
+ * the notation at notationDeclIndex.
+ */
+ public boolean getNotationDecl(int notationDeclIndex, XMLNotationDecl notationDecl) {
+ if (notationDeclIndex < 0 || notationDeclIndex >= fNotationCount) {
+ return false;
+ }
+ int chunk = notationDeclIndex >> CHUNK_SHIFT;
+ int index = notationDeclIndex & CHUNK_MASK;
+
+ notationDecl.setValues(fNotationName[chunk][index],
+ fNotationPublicId[chunk][index],
+ fNotationSystemId[chunk][index],
+ fNotationBaseSystemId[chunk][index]);
+
+ return true;
+
+ } // getNotationDecl
+
+ /**
+ * getContentSpec
+ *
+ * @param contentSpecIndex
+ * @param contentSpec
+ *
+ * @return true if find the requested contentSpec node, false otherwise
+ */
+ public boolean getContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) {
+ if (contentSpecIndex < 0 || contentSpecIndex >= fContentSpecCount )
+ return false;
+
+ int chunk = contentSpecIndex >> CHUNK_SHIFT;
+ int index = contentSpecIndex & CHUNK_MASK;
+
+ contentSpec.type = fContentSpecType[chunk][index];
+ contentSpec.value = fContentSpecValue[chunk][index];
+ contentSpec.otherValue = fContentSpecOtherValue[chunk][index];
+ return true;
+ }
+
+ /**
+ * Returns the index to the content spec for the given element
+ * declaration, or -1 if the element declaration
+ * index was invalid.
+ */
+ public int getContentSpecIndex(int elementDeclIndex) {
+ if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
+ return -1;
+ }
+ final int chunk = elementDeclIndex >> CHUNK_SHIFT;
+ final int index = elementDeclIndex & CHUNK_MASK;
+ return fElementDeclContentSpecIndex[chunk][index];
+ }
+
+ /**
+ * getContentSpecAsString
+ *
+ * @param elementDeclIndex
+ *
+ * @return String
+ */
+ public String getContentSpecAsString(int elementDeclIndex){
+
+ if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
+ return null;
+ }
+
+ int chunk = elementDeclIndex >> CHUNK_SHIFT;
+ int index = elementDeclIndex & CHUNK_MASK;
+
+ int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index];
+
+ // lookup content spec node
+ XMLContentSpec contentSpec = new XMLContentSpec();
+
+ if (getContentSpec(contentSpecIndex, contentSpec)) {
+
+ // build string
+ StringBuffer str = new StringBuffer();
+ int parentContentSpecType = contentSpec.type & 0x0f;
+ int nextContentSpec;
+ switch (parentContentSpecType) {
+ case XMLContentSpec.CONTENTSPECNODE_LEAF: {
+ str.append('(');
+ if (contentSpec.value == null && contentSpec.otherValue == null) {
+ str.append("#PCDATA");
+ }
+ else {
+ str.append(contentSpec.value);
+ }
+ str.append(')');
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
+ getContentSpec(((int[])contentSpec.value)[0], contentSpec);
+ nextContentSpec = contentSpec.type;
+
+ if (nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
+ str.append('(');
+ str.append(contentSpec.value);
+ str.append(')');
+ } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
+ nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
+ nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
+ str.append('(' );
+ appendContentSpec(contentSpec, str,
+ true, parentContentSpecType );
+ str.append(')');
+ } else {
+ appendContentSpec(contentSpec, str,
+ true, parentContentSpecType );
+ }
+ str.append('?');
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
+ getContentSpec(((int[])contentSpec.value)[0], contentSpec);
+ nextContentSpec = contentSpec.type;
+
+ if ( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
+ str.append('(');
+ if (contentSpec.value == null && contentSpec.otherValue == null) {
+ str.append("#PCDATA");
+ }
+ else if (contentSpec.otherValue != null) {
+ str.append("##any:uri=").append(contentSpec.otherValue);
+ }
+ else if (contentSpec.value == null) {
+ str.append("##any");
+ }
+ else {
+ appendContentSpec(contentSpec, str,
+ true, parentContentSpecType );
+ }
+ str.append(')');
+ } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
+ nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
+ nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
+ str.append('(' );
+ appendContentSpec(contentSpec, str,
+ true, parentContentSpecType );
+ str.append(')');
+ } else {
+ appendContentSpec(contentSpec, str,
+ true, parentContentSpecType );
+ }
+ str.append('*');
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
+ getContentSpec(((int[])contentSpec.value)[0], contentSpec);
+ nextContentSpec = contentSpec.type;
+
+ if ( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_LEAF) {
+ str.append('(');
+ if (contentSpec.value == null && contentSpec.otherValue == null) {
+ str.append("#PCDATA");
+ }
+ else if (contentSpec.otherValue != null) {
+ str.append("##any:uri=").append(contentSpec.otherValue);
+ }
+ else if (contentSpec.value == null) {
+ str.append("##any");
+ }
+ else {
+ str.append(contentSpec.value);
+ }
+ str.append(')');
+ } else if( nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
+ nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
+ nextContentSpec == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
+ str.append('(' );
+ appendContentSpec(contentSpec, str,
+ true, parentContentSpecType );
+ str.append(')');
+ } else {
+ appendContentSpec(contentSpec, str,
+ true, parentContentSpecType);
+ }
+ str.append('+');
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_CHOICE:
+ case XMLContentSpec.CONTENTSPECNODE_SEQ: {
+ appendContentSpec(contentSpec, str,
+ true, parentContentSpecType );
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_ANY: {
+ str.append("##any");
+ if (contentSpec.otherValue != null) {
+ str.append(":uri=");
+ str.append(contentSpec.otherValue);
+ }
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: {
+ str.append("##other:uri=");
+ str.append(contentSpec.otherValue);
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: {
+ str.append("##local");
+ break;
+ }
+ default: {
+ str.append("???");
+ }
+
+ } // switch type
+
+ // return string
+ return str.toString();
+ }
+
+ // not found
+ return null;
+
+ } // getContentSpecAsString(int):String
+
+ // debugging
+
+ public void printElements( ) {
+ int elementDeclIndex = 0;
+ XMLElementDecl elementDecl = new XMLElementDecl();
+ while (getElementDecl(elementDeclIndex++, elementDecl)) {
+
+ System.out.println("element decl: "+elementDecl.name+
+ ", "+ elementDecl.name.rawname );
+
+ // ", "+ elementDecl.contentModelValidator.toString());
+ }
+ }
+
+ public void printAttributes(int elementDeclIndex) {
+ int attributeDeclIndex = getFirstAttributeDeclIndex(elementDeclIndex);
+ System.out.print(elementDeclIndex);
+ System.out.print(" [");
+ while (attributeDeclIndex != -1) {
+ System.out.print(' ');
+ System.out.print(attributeDeclIndex);
+ printAttribute(attributeDeclIndex);
+ attributeDeclIndex = getNextAttributeDeclIndex(attributeDeclIndex);
+ if (attributeDeclIndex != -1) {
+ System.out.print(",");
+ }
+ }
+ System.out.println(" ]");
+ }
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * Adds the content spec to the given element declaration.
+ */
+ protected void addContentSpecToElement(XMLElementDecl elementDecl) {
+ if ((fDepth == 0 || (fDepth == 1 && elementDecl.type == XMLElementDecl.TYPE_MIXED)) &&
+ fNodeIndexStack != null) {
+ if (elementDecl.type == XMLElementDecl.TYPE_MIXED) {
+ int pcdata = addUniqueLeafNode(null);
+ if (fNodeIndexStack[0] == -1) {
+ fNodeIndexStack[0] = pcdata;
+ }
+ else {
+ fNodeIndexStack[0] = addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE,
+ pcdata, fNodeIndexStack[0]);
+ }
+ }
+ setContentSpecIndex(fCurrentElementIndex, fNodeIndexStack[fDepth]);
+ }
+ }
+
+ /**
+ * getElementContentModelValidator
+ *
+ * @param elementDeclIndex
+ *
+ * @return its ContentModelValidator if any.
+ */
+ protected ContentModelValidator getElementContentModelValidator(int elementDeclIndex) {
+
+ int chunk = elementDeclIndex >> CHUNK_SHIFT;
+ int index = elementDeclIndex & CHUNK_MASK;
+
+ ContentModelValidator contentModel = fElementDeclContentModelValidator[chunk][index];
+
+ // If we have one, just return that. Otherwise, gotta create one
+ if (contentModel != null) {
+ return contentModel;
+ }
+
+ int contentType = fElementDeclType[chunk][index];
+ if (contentType == XMLElementDecl.TYPE_SIMPLE) {
+ return null;
+ }
+
+ // Get the type of content this element has
+ int contentSpecIndex = fElementDeclContentSpecIndex[chunk][index];
+
+ /***
+ if ( contentSpecIndex == -1 )
+ return null;
+ /***/
+
+ XMLContentSpec contentSpec = new XMLContentSpec();
+ getContentSpec( contentSpecIndex, contentSpec );
+
+ // And create the content model according to the spec type
+ if ( contentType == XMLElementDecl.TYPE_MIXED ) {
+ //
+ // Just create a mixel content model object. This type of
+ // content model is optimized for mixed content validation.
+ //
+ ChildrenList children = new ChildrenList();
+ contentSpecTree(contentSpecIndex, contentSpec, children);
+ contentModel = new MixedContentModel(children.qname,
+ children.type,
+ 0, children.length,
+ false);
+ } else if (contentType == XMLElementDecl.TYPE_CHILDREN) {
+ // This method will create an optimal model for the complexity
+ // of the element's defined model. If its simple, it will create
+ // a SimpleContentModel object. If its a simple list, it will
+ // create a SimpleListContentModel object. If its complex, it
+ // will create a DFAContentModel object.
+ //
+ contentModel = createChildModel(contentSpecIndex);
+ } else {
+ throw new RuntimeException("Unknown content type for a element decl "
+ + "in getElementContentModelValidator() in AbstractDTDGrammar class");
+ }
+
+ // Add the new model to the content model for this element
+ fElementDeclContentModelValidator[chunk][index] = contentModel;
+
+ return contentModel;
+
+ } // getElementContentModelValidator(int):ContentModelValidator
+
+ protected int createElementDecl() {
+ int chunk = fElementDeclCount >> CHUNK_SHIFT;
+ int index = fElementDeclCount & CHUNK_MASK;
+ ensureElementDeclCapacity(chunk);
+ fElementDeclName[chunk][index] = new QName();
+ fElementDeclType[chunk][index] = -1;
+ fElementDeclContentModelValidator[chunk][index] = null;
+ fElementDeclFirstAttributeDeclIndex[chunk][index] = -1;
+ fElementDeclLastAttributeDeclIndex[chunk][index] = -1;
+ return fElementDeclCount++;
+ }
+
+ protected void setElementDecl(int elementDeclIndex, XMLElementDecl elementDecl) {
+ if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
+ return;
+ }
+ int chunk = elementDeclIndex >> CHUNK_SHIFT;
+ int index = elementDeclIndex & CHUNK_MASK;
+
+ fElementDeclName[chunk][index].setValues(elementDecl.name);
+ fElementDeclType[chunk][index] = elementDecl.type;
+
+ fElementDeclContentModelValidator[chunk][index] = elementDecl.contentModelValidator;
+
+ if (elementDecl.simpleType.list == true ) {
+ fElementDeclType[chunk][index] |= LIST_FLAG;
+ }
+
+ fElementIndexMap.put(elementDecl.name.rawname, elementDeclIndex);
+ }
+
+
+
+
+ protected void putElementNameMapping(QName name, int scope,
+ int elementDeclIndex) {
+ }
+
+ protected void setFirstAttributeDeclIndex(int elementDeclIndex, int newFirstAttrIndex){
+
+ if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
+ return;
+ }
+
+ int chunk = elementDeclIndex >> CHUNK_SHIFT;
+ int index = elementDeclIndex & CHUNK_MASK;
+
+ fElementDeclFirstAttributeDeclIndex[chunk][index] = newFirstAttrIndex;
+ }
+
+ protected void setContentSpecIndex(int elementDeclIndex, int contentSpecIndex){
+
+ if (elementDeclIndex < 0 || elementDeclIndex >= fElementDeclCount) {
+ return;
+ }
+
+ int chunk = elementDeclIndex >> CHUNK_SHIFT;
+ int index = elementDeclIndex & CHUNK_MASK;
+
+ fElementDeclContentSpecIndex[chunk][index] = contentSpecIndex;
+ }
+
+
+ protected int createAttributeDecl() {
+ int chunk = fAttributeDeclCount >> CHUNK_SHIFT;
+ int index = fAttributeDeclCount & CHUNK_MASK;
+
+ ensureAttributeDeclCapacity(chunk);
+ fAttributeDeclName[chunk][index] = new QName();
+ fAttributeDeclType[chunk][index] = -1;
+ fAttributeDeclDatatypeValidator[chunk][index] = null;
+ fAttributeDeclEnumeration[chunk][index] = null;
+ fAttributeDeclDefaultType[chunk][index] = XMLSimpleType.DEFAULT_TYPE_IMPLIED;
+ fAttributeDeclDefaultValue[chunk][index] = null;
+ fAttributeDeclNonNormalizedDefaultValue[chunk][index] = null;
+ fAttributeDeclNextAttributeDeclIndex[chunk][index] = -1;
+ return fAttributeDeclCount++;
+ }
+
+
+ protected void setAttributeDecl(int elementDeclIndex, int attributeDeclIndex,
+ XMLAttributeDecl attributeDecl) {
+ int attrChunk = attributeDeclIndex >> CHUNK_SHIFT;
+ int attrIndex = attributeDeclIndex & CHUNK_MASK;
+ fAttributeDeclName[attrChunk][attrIndex].setValues(attributeDecl.name);
+ fAttributeDeclType[attrChunk][attrIndex] = attributeDecl.simpleType.type;
+
+ if (attributeDecl.simpleType.list) {
+ fAttributeDeclType[attrChunk][attrIndex] |= LIST_FLAG;
+ }
+ fAttributeDeclEnumeration[attrChunk][attrIndex] = attributeDecl.simpleType.enumeration;
+ fAttributeDeclDefaultType[attrChunk][attrIndex] = attributeDecl.simpleType.defaultType;
+ fAttributeDeclDatatypeValidator[attrChunk][attrIndex] = attributeDecl.simpleType.datatypeValidator;
+
+ fAttributeDeclDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.defaultValue;
+ fAttributeDeclNonNormalizedDefaultValue[attrChunk][attrIndex] = attributeDecl.simpleType.nonNormalizedDefaultValue;
+
+ int elemChunk = elementDeclIndex >> CHUNK_SHIFT;
+ int elemIndex = elementDeclIndex & CHUNK_MASK;
+ int index = fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex];
+ while (index != -1) {
+ if (index == attributeDeclIndex) {
+ break;
+ }
+ attrChunk = index >> CHUNK_SHIFT;
+ attrIndex = index & CHUNK_MASK;
+ index = fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex];
+ }
+ if (index == -1) {
+ if (fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] == -1) {
+ fElementDeclFirstAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
+ } else {
+ index = fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex];
+ attrChunk = index >> CHUNK_SHIFT;
+ attrIndex = index & CHUNK_MASK;
+ fAttributeDeclNextAttributeDeclIndex[attrChunk][attrIndex] = attributeDeclIndex;
+ }
+ fElementDeclLastAttributeDeclIndex[elemChunk][elemIndex] = attributeDeclIndex;
+ }
+ }
+
+ protected int createContentSpec() {
+ int chunk = fContentSpecCount >> CHUNK_SHIFT;
+ int index = fContentSpecCount & CHUNK_MASK;
+
+ ensureContentSpecCapacity(chunk);
+ fContentSpecType[chunk][index] = -1;
+ fContentSpecValue[chunk][index] = null;
+ fContentSpecOtherValue[chunk][index] = null;
+
+ return fContentSpecCount++;
+ }
+
+ protected void setContentSpec(int contentSpecIndex, XMLContentSpec contentSpec) {
+ int chunk = contentSpecIndex >> CHUNK_SHIFT;
+ int index = contentSpecIndex & CHUNK_MASK;
+
+ fContentSpecType[chunk][index] = contentSpec.type;
+ fContentSpecValue[chunk][index] = contentSpec.value;
+ fContentSpecOtherValue[chunk][index] = contentSpec.otherValue;
+ }
+
+
+ protected int createEntityDecl() {
+ int chunk = fEntityCount >> CHUNK_SHIFT;
+ int index = fEntityCount & CHUNK_MASK;
+
+ ensureEntityDeclCapacity(chunk);
+ fEntityIsPE[chunk][index] = 0;
+ fEntityInExternal[chunk][index] = 0;
+
+ return fEntityCount++;
+ }
+
+ protected void setEntityDecl(int entityDeclIndex, XMLEntityDecl entityDecl) {
+ int chunk = entityDeclIndex >> CHUNK_SHIFT;
+ int index = entityDeclIndex & CHUNK_MASK;
+
+ fEntityName[chunk][index] = entityDecl.name;
+ fEntityValue[chunk][index] = entityDecl.value;
+ fEntityPublicId[chunk][index] = entityDecl.publicId;
+ fEntitySystemId[chunk][index] = entityDecl.systemId;
+ fEntityBaseSystemId[chunk][index] = entityDecl.baseSystemId;
+ fEntityNotation[chunk][index] = entityDecl.notation;
+ fEntityIsPE[chunk][index] = entityDecl.isPE ? (byte)1 : (byte)0;
+ fEntityInExternal[chunk][index] = entityDecl.inExternal ? (byte)1 : (byte)0;
+
+ fEntityIndexMap.put(entityDecl.name, entityDeclIndex);
+ }
+
+ protected int createNotationDecl() {
+ int chunk = fNotationCount >> CHUNK_SHIFT;
+ ensureNotationDeclCapacity(chunk);
+ return fNotationCount++;
+ }
+
+ protected void setNotationDecl(int notationDeclIndex, XMLNotationDecl notationDecl) {
+ int chunk = notationDeclIndex >> CHUNK_SHIFT;
+ int index = notationDeclIndex & CHUNK_MASK;
+
+ fNotationName[chunk][index] = notationDecl.name;
+ fNotationPublicId[chunk][index] = notationDecl.publicId;
+ fNotationSystemId[chunk][index] = notationDecl.systemId;
+ fNotationBaseSystemId[chunk][index] = notationDecl.baseSystemId;
+
+ fNotationIndexMap.put(notationDecl.name, notationDeclIndex);
+ }
+
+ /**
+ * Create an XMLContentSpec for a single non-leaf
+ *
+ * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
+ * @param nodeValue handle to an XMLContentSpec
+ * @return handle to the newly create XMLContentSpec
+ */
+ protected int addContentSpecNode(short nodeType, String nodeValue) {
+
+ // create content spec node
+ int contentSpecIndex = createContentSpec();
+
+ // set content spec node values
+ fContentSpec.setValues(nodeType, nodeValue, null);
+ setContentSpec(contentSpecIndex, fContentSpec);
+
+ // return index
+ return contentSpecIndex;
+
+ } // addContentSpecNode(short,String):int
+
+ /**
+ * create an XMLContentSpec for a leaf
+ *
+ * @param elementName the name (Element) for the node
+ * @return handle to the newly create XMLContentSpec
+ */
+ protected int addUniqueLeafNode(String elementName) {
+
+ // create content spec node
+ int contentSpecIndex = createContentSpec();
+
+ // set content spec node values
+ fContentSpec.setValues( XMLContentSpec.CONTENTSPECNODE_LEAF,
+ elementName, null);
+ setContentSpec(contentSpecIndex, fContentSpec);
+
+ // return index
+ return contentSpecIndex;
+
+ } // addUniqueLeafNode(String):int
+
+ /**
+ * Create an XMLContentSpec for a two child leaf
+ *
+ * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
+ * @param leftNodeIndex handle to an XMLContentSpec
+ * @param rightNodeIndex handle to an XMLContentSpec
+ * @return handle to the newly create XMLContentSpec
+ */
+ protected int addContentSpecNode(short nodeType,
+ int leftNodeIndex, int rightNodeIndex) {
+
+ // create content spec node
+ int contentSpecIndex = createContentSpec();
+
+ // set content spec node values
+ int[] leftIntArray = new int[1];
+ int[] rightIntArray = new int[1];
+
+ leftIntArray[0] = leftNodeIndex;
+ rightIntArray[0] = rightNodeIndex;
+ fContentSpec.setValues(nodeType, leftIntArray, rightIntArray);
+ setContentSpec(contentSpecIndex, fContentSpec);
+
+ // return index
+ return contentSpecIndex;
+
+ } // addContentSpecNode(short,int,int):int
+
+ /** Initialize content model stack. */
+ protected void initializeContentModelStack() {
+
+ if (fOpStack == null) {
+ fOpStack = new short[8];
+ fNodeIndexStack = new int[8];
+ fPrevNodeIndexStack = new int[8];
+ } else if (fDepth == fOpStack.length) {
+ short[] newStack = new short[fDepth * 2];
+ System.arraycopy(fOpStack, 0, newStack, 0, fDepth);
+ fOpStack = newStack;
+ int[] newIntStack = new int[fDepth * 2];
+ System.arraycopy(fNodeIndexStack, 0, newIntStack, 0, fDepth);
+ fNodeIndexStack = newIntStack;
+ newIntStack = new int[fDepth * 2];
+ System.arraycopy(fPrevNodeIndexStack, 0, newIntStack, 0, fDepth);
+ fPrevNodeIndexStack = newIntStack;
+ }
+ fOpStack[fDepth] = -1;
+ fNodeIndexStack[fDepth] = -1;
+ fPrevNodeIndexStack[fDepth] = -1;
+
+ } // initializeContentModelStack()
+
+ boolean isImmutable() {
+ return fIsImmutable;
+ }
+
+ //
+ // Private methods
+ //
+
+ private void appendContentSpec(XMLContentSpec contentSpec,
+ StringBuffer str, boolean parens,
+ int parentContentSpecType ) {
+
+ int thisContentSpec = contentSpec.type & 0x0f;
+ switch (thisContentSpec) {
+ case XMLContentSpec.CONTENTSPECNODE_LEAF: {
+ if (contentSpec.value == null && contentSpec.otherValue == null) {
+ str.append("#PCDATA");
+ }
+ else if (contentSpec.value == null && contentSpec.otherValue != null) {
+ str.append("##any:uri=").append(contentSpec.otherValue);
+ }
+ else if (contentSpec.value == null) {
+ str.append("##any");
+ }
+ else {
+ str.append(contentSpec.value);
+ }
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE: {
+ if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
+ parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
+ parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
+ getContentSpec(((int[])contentSpec.value)[0], contentSpec);
+ str.append('(');
+ appendContentSpec(contentSpec, str, true, thisContentSpec );
+ str.append(')');
+ }
+ else {
+ getContentSpec(((int[])contentSpec.value)[0], contentSpec);
+ appendContentSpec( contentSpec, str, true, thisContentSpec );
+ }
+ str.append('?');
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE: {
+ if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
+ parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
+ parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
+ getContentSpec(((int[])contentSpec.value)[0], contentSpec);
+ str.append('(');
+ appendContentSpec(contentSpec, str, true, thisContentSpec);
+ str.append(')' );
+ }
+ else {
+ getContentSpec(((int[])contentSpec.value)[0], contentSpec);
+ appendContentSpec(contentSpec, str, true, thisContentSpec);
+ }
+ str.append('*');
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE: {
+ if (parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE ||
+ parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
+ parentContentSpecType == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ) {
+
+ str.append('(');
+ getContentSpec(((int[])contentSpec.value)[0], contentSpec);
+ appendContentSpec(contentSpec, str, true, thisContentSpec);
+ str.append(')' );
+ }
+ else {
+ getContentSpec(((int[])contentSpec.value)[0], contentSpec);
+ appendContentSpec(contentSpec, str, true, thisContentSpec);
+ }
+ str.append('+');
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_CHOICE:
+ case XMLContentSpec.CONTENTSPECNODE_SEQ: {
+ if (parens) {
+ str.append('(');
+ }
+ int type = contentSpec.type;
+ int otherValue = ((int[])contentSpec.otherValue)[0];
+ getContentSpec(((int[])contentSpec.value)[0], contentSpec);
+ appendContentSpec(contentSpec, str, contentSpec.type != type, thisContentSpec);
+ if (type == XMLContentSpec.CONTENTSPECNODE_CHOICE) {
+ str.append('|');
+ }
+ else {
+ str.append(',');
+ }
+ getContentSpec(otherValue, contentSpec);
+ appendContentSpec(contentSpec, str, true, thisContentSpec);
+ if (parens) {
+ str.append(')');
+ }
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_ANY: {
+ str.append("##any");
+ if (contentSpec.otherValue != null) {
+ str.append(":uri=");
+ str.append(contentSpec.otherValue);
+ }
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER: {
+ str.append("##other:uri=");
+ str.append(contentSpec.otherValue);
+ break;
+ }
+ case XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL: {
+ str.append("##local");
+ break;
+ }
+ default: {
+ str.append("???");
+ break;
+ }
+
+ } // switch type
+
+ } // appendContentSpec(XMLContentSpec.Provider,StringPool,XMLContentSpec,StringBuffer,boolean)
+
+ // debugging
+
+ private void printAttribute(int attributeDeclIndex) {
+
+ XMLAttributeDecl attributeDecl = new XMLAttributeDecl();
+ if (getAttributeDecl(attributeDeclIndex, attributeDecl)) {
+ System.out.print(" { ");
+ System.out.print(attributeDecl.name.localpart);
+ System.out.print(" }");
+ }
+
+ } // printAttribute(int)
+
+ // content models
+
+ /**
+ * When the element has a 'CHILDREN' model, this method is called to
+ * create the content model object. It looks for some special case simple
+ * models and creates SimpleContentModel objects for those. For the rest
+ * it creates the standard DFA style model.
+ */
+ private synchronized ContentModelValidator createChildModel(int contentSpecIndex) {
+
+ //
+ // Get the content spec node for the element we are working on.
+ // This will tell us what kind of node it is, which tells us what
+ // kind of model we will try to create.
+ //
+ XMLContentSpec contentSpec = new XMLContentSpec();
+ getContentSpec(contentSpecIndex, contentSpec);
+
+ if ((contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY ||
+ (contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER ||
+ (contentSpec.type & 0x0f ) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
+ // let fall through to build a DFAContentModel
+ }
+
+ else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
+ //
+ // Check that the left value is not -1, since any content model
+ // with PCDATA should be MIXED, so we should not have gotten here.
+ //
+ if (contentSpec.value == null && contentSpec.otherValue == null)
+ throw new RuntimeException("ImplementationMessages.VAL_NPCD");
+
+ //
+ // Its a single leaf, so its an 'a' type of content model, i.e.
+ // just one instance of one element. That one is definitely a
+ // simple content model.
+ //
+
+ fQName.setValues(null, (String)contentSpec.value,
+ (String)contentSpec.value, (String)contentSpec.otherValue);
+ return new SimpleContentModel(contentSpec.type, fQName, null);
+ } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
+ || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
+ //
+ // Lets see if both of the children are leafs. If so, then it
+ // it has to be a simple content model
+ //
+ XMLContentSpec contentSpecLeft = new XMLContentSpec();
+ XMLContentSpec contentSpecRight = new XMLContentSpec();
+
+ getContentSpec( ((int[])contentSpec.value)[0], contentSpecLeft);
+ getContentSpec( ((int[])contentSpec.otherValue)[0], contentSpecRight);
+
+ if ((contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF)
+ && (contentSpecRight.type == XMLContentSpec.CONTENTSPECNODE_LEAF)) {
+ //
+ // Its a simple choice or sequence, so we can do a simple
+ // content model for it.
+ //
+ fQName.setValues(null, (String)contentSpecLeft.value,
+ (String)contentSpecLeft.value, (String)contentSpecLeft.otherValue);
+ fQName2.setValues(null, (String)contentSpecRight.value,
+ (String)contentSpecRight.value, (String)contentSpecRight.otherValue);
+ return new SimpleContentModel(contentSpec.type, fQName, fQName2);
+ }
+ } else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE)
+ || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE)
+ || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE)) {
+ //
+ // Its a repetition, so see if its one child is a leaf. If so
+ // its a repetition of a single element, so we can do a simple
+ // content model for that.
+ //
+ XMLContentSpec contentSpecLeft = new XMLContentSpec();
+ getContentSpec(((int[])contentSpec.value)[0], contentSpecLeft);
+
+ if (contentSpecLeft.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
+ //
+ // It is, so we can create a simple content model here that
+ // will check for this repetition. We pass -1 for the unused
+ // right node.
+ //
+ fQName.setValues(null, (String)contentSpecLeft.value,
+ (String)contentSpecLeft.value, (String)contentSpecLeft.otherValue);
+ return new SimpleContentModel(contentSpec.type, fQName, null);
+ }
+ } else {
+ throw new RuntimeException("ImplementationMessages.VAL_CST");
+ }
+
+ //
+ // Its not a simple content model, so here we have to create a DFA
+ // for this element. So we create a DFAContentModel object. He
+ // encapsulates all of the work to create the DFA.
+ //
+
+ fLeafCount = 0;
+ //int leafCount = countLeaves(contentSpecIndex);
+ fLeafCount = 0;
+ CMNode cmn = buildSyntaxTree(contentSpecIndex, contentSpec);
+
+ // REVISIT: has to be fLeafCount because we convert x+ to x,x*, one more leaf
+ return new DFAContentModel( cmn, fLeafCount, false);
+
+ } // createChildModel(int):ContentModelValidator
+
+ private final CMNode buildSyntaxTree(int startNode,
+ XMLContentSpec contentSpec) {
+
+ // We will build a node at this level for the new tree
+ CMNode nodeRet = null;
+ getContentSpec(startNode, contentSpec);
+ if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY) {
+ //nodeRet = new CMAny(contentSpec.type, -1, fLeafCount++);
+ nodeRet = new CMAny(contentSpec.type, (String)contentSpec.otherValue, fLeafCount++);
+ }
+ else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
+ nodeRet = new CMAny(contentSpec.type, (String)contentSpec.otherValue, fLeafCount++);
+ }
+ else if ((contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
+ nodeRet = new CMAny(contentSpec.type, null, fLeafCount++);
+ }
+ //
+ // If this node is a leaf, then its an easy one. We just add it
+ // to the tree.
+ //
+ else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
+ //
+ // Create a new leaf node, and pass it the current leaf count,
+ // which is its DFA state position. Bump the leaf count after
+ // storing it. This makes the positions zero based since we
+ // store first and then increment.
+ //
+ fQName.setValues(null, (String)contentSpec.value,
+ (String)contentSpec.value, (String)contentSpec.otherValue);
+ nodeRet = new CMLeaf(fQName, fLeafCount++);
+ }
+ else {
+ //
+ // Its not a leaf, so we have to recurse its left and maybe right
+ // nodes. Save both values before we recurse and trash the node.
+ final int leftNode = ((int[])contentSpec.value)[0];
+ final int rightNode = ((int[])contentSpec.otherValue)[0];
+
+ if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
+ || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
+ //
+ // Recurse on both children, and return a binary op node
+ // with the two created sub nodes as its children. The node
+ // type is the same type as the source.
+ //
+
+ nodeRet = new CMBinOp( contentSpec.type, buildSyntaxTree(leftNode, contentSpec)
+ , buildSyntaxTree(rightNode, contentSpec));
+ }
+ else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE) {
+ nodeRet = new CMUniOp( contentSpec.type, buildSyntaxTree(leftNode, contentSpec));
+ }
+ else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
+ || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE
+ || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
+ nodeRet = new CMUniOp(contentSpec.type, buildSyntaxTree(leftNode, contentSpec));
+ }
+ else {
+ throw new RuntimeException("ImplementationMessages.VAL_CST");
+ }
+ }
+ // And return our new node for this level
+ return nodeRet;
+ }
+
+ /**
+ * Build a vector of valid QNames from Content Spec
+ * table.
+ *
+ * @param contentSpecIndex
+ * Content Spec index
+ * @param vectorQName
+ * Array of QName
+ * @exception RuntimeException
+ */
+ private void contentSpecTree(int contentSpecIndex,
+ XMLContentSpec contentSpec,
+ ChildrenList children) {
+
+ // Handle any and leaf nodes
+ getContentSpec( contentSpecIndex, contentSpec);
+ if ( contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF ||
+ (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY ||
+ (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL ||
+ (contentSpec.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
+
+ // resize arrays, if needed
+ if (children.length == children.qname.length) {
+ QName[] newQName = new QName[children.length * 2];
+ System.arraycopy(children.qname, 0, newQName, 0, children.length);
+ children.qname = newQName;
+ int[] newType = new int[children.length * 2];
+ System.arraycopy(children.type, 0, newType, 0, children.length);
+ children.type = newType;
+ }
+
+ // save values and return length
+ children.qname[children.length] = new QName(null, (String)contentSpec.value,
+ (String) contentSpec.value,
+ (String) contentSpec.otherValue);
+ children.type[children.length] = contentSpec.type;
+ children.length++;
+ return;
+ }
+
+ //
+ // Its not a leaf, so we have to recurse its left and maybe right
+ // nodes. Save both values before we recurse and trash the node.
+ //
+ final int leftNode = contentSpec.value != null
+ ? ((int[])(contentSpec.value))[0] : -1;
+ int rightNode = -1 ;
+ if (contentSpec.otherValue != null )
+ rightNode = ((int[])(contentSpec.otherValue))[0];
+ else
+ return;
+
+ if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE ||
+ contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
+ contentSpecTree(leftNode, contentSpec, children);
+ contentSpecTree(rightNode, contentSpec, children);
+ return;
+ }
+
+ if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE ||
+ contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE ||
+ contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
+ contentSpecTree(leftNode, contentSpec, children);
+ return;
+ }
+
+ // error
+ throw new RuntimeException("Invalid content spec type seen in contentSpecTree() method of AbstractDTDGrammar class : "+contentSpec.type);
+
+ } // contentSpecTree(int,XMLContentSpec,ChildrenList)
+
+ // ensure capacity
+
+ private void ensureElementDeclCapacity(int chunk) {
+ if (chunk >= fElementDeclName.length) {
+ fElementDeclIsExternal = resize(fElementDeclIsExternal,
+ fElementDeclIsExternal.length * 2);
+
+ fElementDeclName = resize(fElementDeclName, fElementDeclName.length * 2);
+ fElementDeclType = resize(fElementDeclType, fElementDeclType.length * 2);
+ fElementDeclContentModelValidator = resize(fElementDeclContentModelValidator, fElementDeclContentModelValidator.length * 2);
+ fElementDeclContentSpecIndex = resize(fElementDeclContentSpecIndex,fElementDeclContentSpecIndex.length * 2);
+ fElementDeclFirstAttributeDeclIndex = resize(fElementDeclFirstAttributeDeclIndex, fElementDeclFirstAttributeDeclIndex.length * 2);
+ fElementDeclLastAttributeDeclIndex = resize(fElementDeclLastAttributeDeclIndex, fElementDeclLastAttributeDeclIndex.length * 2);
+ }
+ else if (fElementDeclName[chunk] != null) {
+ return;
+ }
+
+ fElementDeclIsExternal[chunk] = new int[CHUNK_SIZE];
+ fElementDeclName[chunk] = new QName[CHUNK_SIZE];
+ fElementDeclType[chunk] = new short[CHUNK_SIZE];
+ fElementDeclContentModelValidator[chunk] = new ContentModelValidator[CHUNK_SIZE];
+ fElementDeclContentSpecIndex[chunk] = new int[CHUNK_SIZE];
+ fElementDeclFirstAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
+ fElementDeclLastAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
+ return;
+ }
+
+ private void ensureAttributeDeclCapacity(int chunk) {
+
+ if (chunk >= fAttributeDeclName.length) {
+ fAttributeDeclIsExternal = resize(fAttributeDeclIsExternal,
+ fAttributeDeclIsExternal.length * 2);
+ fAttributeDeclName = resize(fAttributeDeclName, fAttributeDeclName.length * 2);
+ fAttributeDeclType = resize(fAttributeDeclType, fAttributeDeclType.length * 2);
+ fAttributeDeclEnumeration = resize(fAttributeDeclEnumeration, fAttributeDeclEnumeration.length * 2);
+ fAttributeDeclDefaultType = resize(fAttributeDeclDefaultType, fAttributeDeclDefaultType.length * 2);
+ fAttributeDeclDatatypeValidator = resize(fAttributeDeclDatatypeValidator, fAttributeDeclDatatypeValidator.length * 2);
+ fAttributeDeclDefaultValue = resize(fAttributeDeclDefaultValue, fAttributeDeclDefaultValue.length * 2);
+ fAttributeDeclNonNormalizedDefaultValue = resize(fAttributeDeclNonNormalizedDefaultValue, fAttributeDeclNonNormalizedDefaultValue.length * 2);
+ fAttributeDeclNextAttributeDeclIndex = resize(fAttributeDeclNextAttributeDeclIndex, fAttributeDeclNextAttributeDeclIndex.length * 2);
+ }
+ else if (fAttributeDeclName[chunk] != null) {
+ return;
+ }
+
+ fAttributeDeclIsExternal[chunk] = new int[CHUNK_SIZE];
+ fAttributeDeclName[chunk] = new QName[CHUNK_SIZE];
+ fAttributeDeclType[chunk] = new short[CHUNK_SIZE];
+ fAttributeDeclEnumeration[chunk] = new String[CHUNK_SIZE][];
+ fAttributeDeclDefaultType[chunk] = new short[CHUNK_SIZE];
+ fAttributeDeclDatatypeValidator[chunk] = new DatatypeValidator[CHUNK_SIZE];
+ fAttributeDeclDefaultValue[chunk] = new String[CHUNK_SIZE];
+ fAttributeDeclNonNormalizedDefaultValue[chunk] = new String[CHUNK_SIZE];
+ fAttributeDeclNextAttributeDeclIndex[chunk] = new int[CHUNK_SIZE];
+ return;
+ }
+
+ private void ensureEntityDeclCapacity(int chunk) {
+ if (chunk >= fEntityName.length) {
+ fEntityName = resize(fEntityName, fEntityName.length * 2);
+ fEntityValue = resize(fEntityValue, fEntityValue.length * 2);
+ fEntityPublicId = resize(fEntityPublicId, fEntityPublicId.length * 2);
+ fEntitySystemId = resize(fEntitySystemId, fEntitySystemId.length * 2);
+ fEntityBaseSystemId = resize(fEntityBaseSystemId, fEntityBaseSystemId.length * 2);
+ fEntityNotation = resize(fEntityNotation, fEntityNotation.length * 2);
+ fEntityIsPE = resize(fEntityIsPE, fEntityIsPE.length * 2);
+ fEntityInExternal = resize(fEntityInExternal, fEntityInExternal.length * 2);
+ }
+ else if (fEntityName[chunk] != null) {
+ return;
+ }
+
+ fEntityName[chunk] = new String[CHUNK_SIZE];
+ fEntityValue[chunk] = new String[CHUNK_SIZE];
+ fEntityPublicId[chunk] = new String[CHUNK_SIZE];
+ fEntitySystemId[chunk] = new String[CHUNK_SIZE];
+ fEntityBaseSystemId[chunk] = new String[CHUNK_SIZE];
+ fEntityNotation[chunk] = new String[CHUNK_SIZE];
+ fEntityIsPE[chunk] = new byte[CHUNK_SIZE];
+ fEntityInExternal[chunk] = new byte[CHUNK_SIZE];
+ return;
+ }
+
+ private void ensureNotationDeclCapacity(int chunk) {
+ if (chunk >= fNotationName.length) {
+ fNotationName = resize(fNotationName, fNotationName.length * 2);
+ fNotationPublicId = resize(fNotationPublicId, fNotationPublicId.length * 2);
+ fNotationSystemId = resize(fNotationSystemId, fNotationSystemId.length * 2);
+ fNotationBaseSystemId = resize(fNotationBaseSystemId, fNotationBaseSystemId.length * 2);
+ }
+ else if (fNotationName[chunk] != null) {
+ return;
+ }
+
+ fNotationName[chunk] = new String[CHUNK_SIZE];
+ fNotationPublicId[chunk] = new String[CHUNK_SIZE];
+ fNotationSystemId[chunk] = new String[CHUNK_SIZE];
+ fNotationBaseSystemId[chunk] = new String[CHUNK_SIZE];
+ return;
+ }
+
+ private void ensureContentSpecCapacity(int chunk) {
+ if (chunk >= fContentSpecType.length) {
+ fContentSpecType = resize(fContentSpecType, fContentSpecType.length * 2);
+ fContentSpecValue = resize(fContentSpecValue, fContentSpecValue.length * 2);
+ fContentSpecOtherValue = resize(fContentSpecOtherValue, fContentSpecOtherValue.length * 2);
+ }
+ else if (fContentSpecType[chunk] != null) {
+ return;
+ }
+
+ fContentSpecType[chunk] = new short[CHUNK_SIZE];
+ fContentSpecValue[chunk] = new Object[CHUNK_SIZE];
+ fContentSpecOtherValue[chunk] = new Object[CHUNK_SIZE];
+ return;
+ }
+
+ //
+ // Private static methods
+ //
+
+ // resize chunks
+
+ private static byte[][] resize(byte array[][], int newsize) {
+ byte newarray[][] = new byte[newsize][];
+ System.arraycopy(array, 0, newarray, 0, array.length);
+ return newarray;
+ }
+
+ private static short[][] resize(short array[][], int newsize) {
+ short newarray[][] = new short[newsize][];
+ System.arraycopy(array, 0, newarray, 0, array.length);
+ return newarray;
+ }
+
+ private static int[][] resize(int array[][], int newsize) {
+ int newarray[][] = new int[newsize][];
+ System.arraycopy(array, 0, newarray, 0, array.length);
+ return newarray;
+ }
+
+ private static DatatypeValidator[][] resize(DatatypeValidator array[][], int newsize) {
+ DatatypeValidator newarray[][] = new DatatypeValidator[newsize][];
+ System.arraycopy(array, 0, newarray, 0, array.length);
+ return newarray;
+ }
+
+ private static ContentModelValidator[][] resize(ContentModelValidator array[][], int newsize) {
+ ContentModelValidator newarray[][] = new ContentModelValidator[newsize][];
+ System.arraycopy(array, 0, newarray, 0, array.length);
+ return newarray;
+ }
+
+ private static Object[][] resize(Object array[][], int newsize) {
+ Object newarray[][] = new Object[newsize][];
+ System.arraycopy(array, 0, newarray, 0, array.length);
+ return newarray;
+ }
+
+ private static QName[][] resize(QName array[][], int newsize) {
+ QName newarray[][] = new QName[newsize][];
+ System.arraycopy(array, 0, newarray, 0, array.length);
+ return newarray;
+ }
+
+ private static String[][] resize(String array[][], int newsize) {
+ String newarray[][] = new String[newsize][];
+ System.arraycopy(array, 0, newarray, 0, array.length);
+ return newarray;
+ }
+
+ private static String[][][] resize(String array[][][], int newsize) {
+ String newarray[][][] = new String[newsize] [][];
+ System.arraycopy(array, 0, newarray, 0, array.length);
+ return newarray;
+ }
+
+ //
+ // Classes
+ //
+
+ /**
+ * Children list for contentSpecTree method.
+ *
+ * @xerces.internal
+ *
+ * @author Eric Ye, IBM
+ */
+ private static class ChildrenList {
+
+ //
+ // Data
+ //
+
+ /** Length. */
+ public int length = 0;
+
+ // NOTE: The following set of data is mutually exclusive. It is
+ // written this way because Java doesn't have a native
+ // union data structure. -Ac
+
+ /** Left and right children names. */
+ public QName[] qname = new QName[2];
+
+ /** Left and right children types. */
+ public int[] type = new int[2];
+
+ //
+ // Constructors
+ //
+
+ public ChildrenList () {}
+
+ } // class ChildrenList
+
+ //
+ // Classes
+ //
+
+ /**
+ * A simple Hashtable implementation that takes a tuple (String, String)
+ * as the key and a int as value.
+ *
+ * @xerces.internal
+ *
+ * @author Eric Ye, IBM
+ * @author Andy Clark, IBM
+ */
+ protected static final class QNameHashtable {
+
+ /**
+ * Fills an array with a random sequence of prime numbers.
+ *
+ * @xerces.internal
+ */
+ private static final class PrimeNumberSequenceGenerator {
+
+ private static int [] PRIMES = {
+ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
+ 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
+ 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
+ 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313,
+ 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
+ 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
+ 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617,
+ 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727};
+
+ static void generateSequence(int[] arrayToFill) {
+ Random r = new Random();
+ for (int i = 0; i < arrayToFill.length; ++i) {
+ arrayToFill[i] = PRIMES[r.nextInt(PRIMES.length)];
+ }
+ }
+ }
+
+ //
+ // Constants
+ //
+
+ /** Initial bucket size (4). */
+ private static final int INITIAL_BUCKET_SIZE = 4;
+
+ // NOTE: Changed previous hashtable size from 512 to 101 so
+ // that we get a better distribution for hashing. -Ac
+ /** Hashtable size (101). */
+ private static final int HASHTABLE_SIZE = 101;
+
+ /** Maximum hash collisions per bucket for a table with load factor == 1. */
+ private static final int MAX_HASH_COLLISIONS = 40;
+
+ private static final int MULTIPLIERS_SIZE = 1 << 5;
+ private static final int MULTIPLIERS_MASK = MULTIPLIERS_SIZE - 1;
+
+ //
+ // Data
+ //
+ private Object[][] fHashTable = new Object[HASHTABLE_SIZE][];
+
+ /** actual table size **/
+ private int fTableSize = HASHTABLE_SIZE;
+
+ /** The total number of entries in the hash table. */
+ private int fCount = 0;
+
+ /**
+ * Array of randomly selected hash function multipliers or null
+ * if the default String.hashCode() function should be used.
+ */
+ private int[] fHashMultipliers;
+
+ //
+ // Public methods
+ //
+ /** Associates the given value with the specified key tuple. */
+ public void put(String key, int value) {
+
+ int hash = (hash(key) & 0x7FFFFFFF) % fTableSize;
+ Object[] bucket = fHashTable[hash];
+
+ if (bucket == null) {
+ bucket = new Object[1 + 2*INITIAL_BUCKET_SIZE];
+ bucket[0] = new int[]{1};
+ bucket[1] = key;
+ bucket[2] = new int[]{value};
+ fHashTable[hash] = bucket;
+ if (++fCount > fTableSize) {
+ // Rehash the table if the number of entries
+ // would exceed the number of buckets.
+ rehash();
+ }
+ } else {
+ int count = ((int[])bucket[0])[0];
+ int offset = 1 + 2*count;
+ if (offset == bucket.length) {
+ int newSize = count + INITIAL_BUCKET_SIZE;
+ Object[] newBucket = new Object[1 + 2*newSize];
+ System.arraycopy(bucket, 0, newBucket, 0, offset);
+ bucket = newBucket;
+ fHashTable[hash] = bucket;
+ }
+ boolean found = false;
+ int j=1;
+ for (int i=0; i fTableSize) {
+ // Rehash the table if the number of entries
+ // would exceed the number of buckets.
+ rehash();
+ }
+ else if (count > MAX_HASH_COLLISIONS) {
+ // Select a new hash function and rehash the table if
+ // MAX_HASH_COLLISIONS is exceeded.
+ rebalance();
+ }
+ }
+
+ }
+ //System.out.println("put("+key+" -> "+value+')');
+ //System.out.println("get("+key+") -> "+get(key));
+
+ } // put(int,String,String,int)
+
+ /** Returns the value associated with the specified key tuple. */
+ public int get(String key) {
+ int hash = (hash(key) & 0x7FFFFFFF) % fTableSize;
+ Object[] bucket = fHashTable[hash];
+
+ if (bucket == null) {
+ return -1;
+ }
+ int count = ((int[])bucket[0])[0];
+
+ int j=1;
+ for (int i=0; i-1) {
+ int chunk = entityIndex >> CHUNK_SHIFT;
+ int index = entityIndex & CHUNK_MASK;
+ //for unparsed entity notation!=null
+ return (fEntityNotation[chunk][index]!=null)?true:false;
+ }
+ return false;
+ }
+} // class DTDGrammar
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/DTDGrammarBucket.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/DTDGrammarBucket.java
new file mode 100644
index 0000000..e7b6f1c
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/DTDGrammarBucket.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import java.util.Hashtable;
+
+import org.apache.xerces.xni.grammars.XMLGrammarDescription;
+
+/**
+ * This very simple class is the skeleton of what the DTDValidator could use
+ * to store various grammars that it gets from the GrammarPool. As in the
+ * case of XSGrammarBucket, one thinks of this object as being closely
+ * associated with its validator; when fully mature, this class will be
+ * filled from the GrammarPool when the DTDValidator is invoked on a
+ * document, and, if a new DTD grammar is parsed, the new set will be
+ * offered back to the GrammarPool for possible inclusion.
+ *
+ * @xerces.internal
+ *
+ * @author Neil Graham, IBM
+ *
+ * @version $Id$
+ */
+public class DTDGrammarBucket {
+
+ // REVISIT: make this class smarter and *way* more complete!
+
+ //
+ // Data
+ //
+
+ /** Grammars associated with element root name. */
+ protected final Hashtable fGrammars;
+
+ // the unique grammar from fGrammars (or that we're
+ // building) that is used in validation.
+ protected DTDGrammar fActiveGrammar;
+
+ // is the "active" grammar standalone?
+ protected boolean fIsStandalone;
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public DTDGrammarBucket() {
+ fGrammars = new Hashtable();
+ } // ()
+
+ //
+ // Public methods
+ //
+
+ /**
+ * Puts the specified grammar into the grammar pool and associate it to
+ * a root element name (this being internal, the lack of generality is irrelevant).
+ *
+ * @param grammar The grammar.
+ */
+ public void putGrammar(DTDGrammar grammar) {
+ XMLDTDDescription desc = (XMLDTDDescription)grammar.getGrammarDescription();
+ fGrammars.put(desc, grammar);
+ } // putGrammar(DTDGrammar)
+
+ // retrieve a DTDGrammar given an XMLDTDDescription
+ public DTDGrammar getGrammar(XMLGrammarDescription desc) {
+ return (DTDGrammar)(fGrammars.get((XMLDTDDescription)desc));
+ } // putGrammar(DTDGrammar)
+
+ public void clear() {
+ fGrammars.clear();
+ fActiveGrammar = null;
+ fIsStandalone = false;
+ } // clear()
+
+ // is the active grammar standalone? This must live here because
+ // at the time the validator discovers this we don't yet know
+ // what the active grammar should be (no info about root)
+ void setStandalone(boolean standalone) {
+ fIsStandalone = standalone;
+ }
+
+ boolean getStandalone() {
+ return fIsStandalone;
+ }
+
+ // set the "active" grammar:
+ void setActiveGrammar (DTDGrammar grammar) {
+ fActiveGrammar = grammar;
+ }
+ DTDGrammar getActiveGrammar () {
+ return fActiveGrammar;
+ }
+} // class DTDGrammarBucket
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XML11DTDProcessor.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XML11DTDProcessor.java
new file mode 100644
index 0000000..2524b71
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XML11DTDProcessor.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.impl.XML11DTDScannerImpl;
+import org.apache.xerces.impl.XMLDTDScannerImpl;
+import org.apache.xerces.impl.XMLEntityManager;
+import org.apache.xerces.impl.XMLErrorReporter;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XML11Char;
+import org.apache.xerces.xni.grammars.XMLGrammarPool;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+
+/**
+ * This class extends XMLDTDProcessor by giving it
+ * the ability to parse XML 1.1 documents correctly. It can also be used
+ * as a DTD loader, so that XML 1.1 external subsets can
+ * be processed correctly (hence it's rather anomalous-appearing
+ * derivation from XMLDTDLoader).
+ *
+ * @xerces.internal
+ *
+ * @author Neil Graham, IBM
+ *
+ * @version $Id$
+ */
+public class XML11DTDProcessor extends XMLDTDLoader{
+
+ // constructors
+
+ public XML11DTDProcessor() {
+ super();
+ } // ()
+
+ public XML11DTDProcessor(SymbolTable symbolTable) {
+ super(symbolTable);
+ } // init(SymbolTable)
+
+ public XML11DTDProcessor(SymbolTable symbolTable,
+ XMLGrammarPool grammarPool) {
+ super(symbolTable, grammarPool);
+ } // init(SymbolTable, XMLGrammarPool)
+
+ XML11DTDProcessor(SymbolTable symbolTable,
+ XMLGrammarPool grammarPool, XMLErrorReporter errorReporter,
+ XMLEntityResolver entityResolver) {
+ super(symbolTable, grammarPool, errorReporter, entityResolver);
+ } // init(SymbolTable, XMLGrammarPool, XMLErrorReporter, XMLEntityResolver)
+
+ // overridden methods
+
+ protected boolean isValidNmtoken(String nmtoken) {
+ return XML11Char.isXML11ValidNmtoken(nmtoken);
+ } // isValidNmtoken(String): boolean
+
+ protected boolean isValidName(String name) {
+ return XML11Char.isXML11ValidName(name);
+ } // isValidNmtoken(String): boolean
+
+ protected XMLDTDScannerImpl createDTDScanner(SymbolTable symbolTable,
+ XMLErrorReporter errorReporter, XMLEntityManager entityManager) {
+ return new XML11DTDScannerImpl(symbolTable, errorReporter, entityManager);
+ } // createDTDScanner(SymbolTable, XMLErrorReporter, XMLEntityManager) : XMLDTDScannerImpl
+
+ protected short getScannerVersion() {
+ return Constants.XML_VERSION_1_1;
+ } // getScannerVersion() : short
+
+} // class XML11DTDProcessor
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XML11DTDValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XML11DTDValidator.java
new file mode 100644
index 0000000..dc27740
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XML11DTDValidator.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+
+/**
+ * This allows the validator to correctlyhandle XML 1.1
+ * documents.
+ *
+ * @xerces.internal
+ *
+ * @author Neil Graham
+ * @version $Id$
+ */
+public class XML11DTDValidator extends XMLDTDValidator {
+
+ //
+ // Constants
+ //
+
+ protected final static String DTD_VALIDATOR_PROPERTY =
+ Constants.XERCES_PROPERTY_PREFIX+Constants.DTD_VALIDATOR_PROPERTY;
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XML11DTDValidator() {
+
+ super();
+ } // ()
+
+ // overridden so that this class has access to the same
+ // grammarBucket as the corresponding DTDProcessor
+ // will try and use...
+ public void reset(XMLComponentManager manager) {
+ XMLDTDValidator curr = null;
+ if((curr = (XMLDTDValidator)manager.getProperty(DTD_VALIDATOR_PROPERTY)) != null &&
+ curr != this) {
+ fGrammarBucket = curr.getGrammarBucket();
+ }
+ super.reset(manager);
+ } //reset(XMLComponentManager)
+
+ protected void init() {
+ if(fValidation || fDynamicValidation) {
+ super.init();
+ // now overwrite some entries in parent:
+
+ try {
+ fValID = fDatatypeValidatorFactory.getBuiltInDV("XML11ID");
+ fValIDRef = fDatatypeValidatorFactory.getBuiltInDV("XML11IDREF");
+ fValIDRefs = fDatatypeValidatorFactory.getBuiltInDV("XML11IDREFS");
+ fValNMTOKEN = fDatatypeValidatorFactory.getBuiltInDV("XML11NMTOKEN");
+ fValNMTOKENS = fDatatypeValidatorFactory.getBuiltInDV("XML11NMTOKENS");
+
+ }
+ catch (Exception e) {
+ // should never happen
+ e.printStackTrace(System.err);
+ }
+ }
+ } // init()
+
+} // class XML11DTDValidator
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XML11NSDTDValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XML11NSDTDValidator.java
new file mode 100644
index 0000000..a9f2fe2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XML11NSDTDValidator.java
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import org.apache.xerces.impl.XMLErrorReporter;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLAttributes;
+import org.apache.xerces.xni.XNIException;
+
+/**
+ * The DTD validator. The validator implements a document
+ * filter: receiving document events from the scanner; validating
+ * the content and structure; augmenting the InfoSet, if applicable;
+ * and notifying the parser of the information resulting from the
+ * validation process.
+ * Formerly, this component also handled DTD events and grammar construction.
+ * To facilitate the development of a meaningful DTD grammar caching/preparsing
+ * framework, this functionality has been moved into the XMLDTDLoader
+ * class. Therefore, this class no longer implements the DTDFilter
+ * or DTDContentModelFilter interfaces.
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/namespaces
+ * - http://xml.org/sax/features/validation
+ * - http://apache.org/xml/features/validation/dynamic
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/grammar-pool
+ * - http://apache.org/xml/properties/internal/datatype-validator-factory
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani, IBM
+ * @author Michael Glavassevich, IBM
+ *
+ * @version $Id$
+ */
+public class XML11NSDTDValidator extends XML11DTDValidator {
+
+ /** Attribute QName. */
+ private final QName fAttributeQName = new QName();
+
+ /** Bind namespaces */
+ protected final void startNamespaceScope(QName element, XMLAttributes attributes, Augmentations augs)
+ throws XNIException {
+
+ // add new namespace context
+ fNamespaceContext.pushContext();
+
+ if (element.prefix == XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementXMLNSPrefix",
+ new Object[] { element.rawname },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // search for new namespace bindings
+ int length = attributes.getLength();
+ for (int i = 0; i < length; i++) {
+ String localpart = attributes.getLocalName(i);
+ String prefix = attributes.getPrefix(i);
+ // when it's of form xmlns="..." or xmlns:prefix="...",
+ // it's a namespace declaration. but prefix:xmlns="..." isn't.
+ if (prefix == XMLSymbols.PREFIX_XMLNS || prefix == XMLSymbols.EMPTY_STRING
+ && localpart == XMLSymbols.PREFIX_XMLNS) {
+
+ // get the internalized value of this attribute
+ String uri = fSymbolTable.addSymbol(attributes.getValue(i));
+
+ // 1. "xmlns" can't be bound to any namespace
+ if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXMLNS",
+ new Object[] { attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // 2. the namespace for "xmlns" can't be bound to any prefix
+ if (uri == NamespaceContext.XMLNS_URI) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXMLNS",
+ new Object[] { attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // 3. "xml" can't be bound to any other namespace than it's own
+ if (localpart == XMLSymbols.PREFIX_XML) {
+ if (uri != NamespaceContext.XML_URI) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXML",
+ new Object[] { attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ // 4. the namespace for "xml" can't be bound to any other prefix
+ else {
+ if (uri == NamespaceContext.XML_URI) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXML",
+ new Object[] { attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+
+ prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING;
+
+ // Declare prefix in context. Removing the association between a prefix and a
+ // namespace name is permitted in XML 1.1, so if the uri value is the empty string,
+ // the prefix is being unbound. -- mrglavas
+ fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null);
+ }
+ }
+
+ // bind the element
+ String prefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING;
+ element.uri = fNamespaceContext.getURI(prefix);
+ if (element.prefix == null && element.uri != null) {
+ element.prefix = XMLSymbols.EMPTY_STRING;
+ }
+ if (element.prefix != null && element.uri == null) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementPrefixUnbound",
+ new Object[] { element.prefix, element.rawname },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // bind the attributes
+ for (int i = 0; i < length; i++) {
+ attributes.getName(i, fAttributeQName);
+ String aprefix = fAttributeQName.prefix != null ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
+ String arawname = fAttributeQName.rawname;
+ if (arawname == XMLSymbols.PREFIX_XMLNS) {
+ fAttributeQName.uri = fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS);
+ attributes.setName(i, fAttributeQName);
+ } else if (aprefix != XMLSymbols.EMPTY_STRING) {
+ fAttributeQName.uri = fNamespaceContext.getURI(aprefix);
+ if (fAttributeQName.uri == null) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributePrefixUnbound",
+ new Object[] { element.rawname, arawname, aprefix },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ attributes.setName(i, fAttributeQName);
+ }
+ }
+
+ // verify that duplicate attributes don't exist
+ // Example:
+ int attrCount = attributes.getLength();
+ for (int i = 0; i < attrCount - 1; i++) {
+ String auri = attributes.getURI(i);
+ if (auri == null || auri == NamespaceContext.XMLNS_URI) {
+ continue;
+ }
+ String alocalpart = attributes.getLocalName(i);
+ for (int j = i + 1; j < attrCount; j++) {
+ String blocalpart = attributes.getLocalName(j);
+ String buri = attributes.getURI(j);
+ if (alocalpart == blocalpart && auri == buri) {
+ fErrorReporter.reportError(
+ XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNSNotUnique",
+ new Object[] { element.rawname, alocalpart, auri },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ }
+
+ } // startNamespaceScope(QName,XMLAttributes)
+
+ /** Handles end element. */
+ protected void endNamespaceScope(QName element, Augmentations augs, boolean isEmpty)
+ throws XNIException {
+
+ // bind element
+ String eprefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING;
+ element.uri = fNamespaceContext.getURI(eprefix);
+ if (element.uri != null) {
+ element.prefix = eprefix;
+ }
+
+ // call handlers
+ if (fDocumentHandler != null) {
+ if (!isEmpty) {
+ fDocumentHandler.endElement(element, augs);
+ }
+ }
+
+ // pop context
+ fNamespaceContext.popContext();
+
+ } // endNamespaceScope(QName,boolean)
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLAttributeDecl.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLAttributeDecl.java
new file mode 100644
index 0000000..c695902
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLAttributeDecl.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import org.apache.xerces.xni.QName;
+
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class XMLAttributeDecl {
+
+ //
+ // Data
+ //
+
+ /** name */
+ public final QName name = new QName();
+
+ /** simpleType */
+ public final XMLSimpleType simpleType = new XMLSimpleType();
+
+ /** optional */
+ public boolean optional;
+
+ //
+ // Methods
+ //
+
+ /**
+ * setValues
+ *
+ * @param name
+ * @param simpleType
+ * @param optional
+ */
+ public void setValues(QName name, XMLSimpleType simpleType, boolean optional) {
+ this.name.setValues(name);
+ this.simpleType.setValues(simpleType);
+ this.optional = optional;
+ } // setValues
+
+ /**
+ * clear
+ */
+ public void clear() {
+ this.name.clear();
+ this.simpleType.clear();
+ this.optional = false;
+ } // clear
+
+} // class XMLAttributeDecl
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLContentSpec.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLContentSpec.java
new file mode 100644
index 0000000..6d4060b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLContentSpec.java
@@ -0,0 +1,294 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+/**
+ * ContentSpec really exists to aid the parser classes in implementing
+ * access to the grammar.
+ *
+ * This class is used by the DTD scanner and the validator classes,
+ * allowing them to be used separately or together. This "struct"
+ * class is used to build content models for validation, where it
+ * is more efficient to fetch all of the information for each of
+ * these content model "fragments" than to fetch each field one at
+ * a time. Since configurations are allowed to have validators
+ * without a DTD scanner (i.e. a schema validator) and a DTD scanner
+ * without a validator (non-validating processor), this class can be
+ * used by each without requiring the presence of the other.
+ *
+ * When processing element declarations, the DTD scanner will build
+ * up a representation of the content model using the node types that
+ * are defined here. Since a non-validating processor only needs to
+ * remember the type of content model declared (i.e. ANY, EMPTY, MIXED,
+ * or CHILDREN), it is free to discard the specific details of the
+ * MIXED and CHILDREN content models described using this class.
+ *
+ * In the typical case of a validating processor reading the grammar
+ * of the document from a DTD, the information about the content model
+ * declared will be preserved and later "compiled" into an efficient
+ * form for use during element validation. Each content spec node
+ * that is saved is assigned a unique index that is used as a handle
+ * for the "value" or "otherValue" fields of other content spec nodes.
+ * A leaf node has a "value" that is either an index in the string
+ * pool of the element type of that leaf, or a value of -1 to indicate
+ * the special "#PCDATA" leaf type used in a mixed content model.
+ *
+ * For a mixed content model, the content spec will be made up of
+ * leaf and choice content spec nodes, with an optional "zero or more"
+ * node. For example, the mixed content declaration "(#PCDATA)" would
+ * contain a single leaf node with a node value of -1. A mixed content
+ * declaration of "(#PCDATA|foo)*" would have a content spec consisting
+ * of two leaf nodes, for the "#PCDATA" and "foo" choices, a choice node
+ * with the "value" set to the index of the "#PCDATA" leaf node and the
+ * "otherValue" set to the index of the "foo" leaf node, and a "zero or
+ * more" node with the "value" set to the index of the choice node. If
+ * the content model has more choices, for example "(#PCDATA|a|b)*", then
+ * there will be more corresponding choice and leaf nodes, the choice
+ * nodes will be chained together through the "value" field with each
+ * leaf node referenced by the "otherValue" field.
+ *
+ * For element content models, there are sequence nodes and also "zero or
+ * one" and "one or more" nodes. The leaf nodes would always have a valid
+ * string pool index, as the "#PCDATA" leaf is not used in the declarations
+ * for element content models.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class XMLContentSpec {
+
+ //
+ // Constants
+ //
+
+ /**
+ * Name or #PCDATA. Leaf nodes that represent parsed character
+ * data (#PCDATA) have values of -1.
+ */
+ public static final short CONTENTSPECNODE_LEAF = 0;
+
+ /** Represents a zero or one occurence count, '?'. */
+ public static final short CONTENTSPECNODE_ZERO_OR_ONE = 1;
+
+ /** Represents a zero or more occurence count, '*'. */
+ public static final short CONTENTSPECNODE_ZERO_OR_MORE = 2;
+
+ /** Represents a one or more occurence count, '+'. */
+ public static final short CONTENTSPECNODE_ONE_OR_MORE = 3;
+
+ /** Represents choice, '|'. */
+ public static final short CONTENTSPECNODE_CHOICE = 4;
+
+ /** Represents sequence, ','. */
+ public static final short CONTENTSPECNODE_SEQ = 5;
+
+ /**
+ * Represents any namespace specified namespace. When the element
+ * found in the document must belong to a specific namespace,
+ * otherValue will contain the name of the namespace.
+ * If otherValue is -1 then the element
+ * can be from any namespace.
+ *
+ * Lists of valid namespaces are created from choice content spec
+ * nodes that have any content spec nodes as children.
+ */
+ public static final short CONTENTSPECNODE_ANY = 6;
+
+ /**
+ * Represents any other namespace (XML Schema: ##other).
+ *
+ * When the content spec node type is set to CONTENTSPECNODE_ANY_OTHER,
+ * value will contain the namespace that cannot
+ * occur.
+ */
+ public static final short CONTENTSPECNODE_ANY_OTHER = 7;
+
+ /** Represents any local element (XML Schema: ##local). */
+ public static final short CONTENTSPECNODE_ANY_LOCAL = 8;
+
+ /** prcessContent is 'lax' **/
+ public static final short CONTENTSPECNODE_ANY_LAX = 22;
+
+ public static final short CONTENTSPECNODE_ANY_OTHER_LAX = 23;
+
+ public static final short CONTENTSPECNODE_ANY_LOCAL_LAX = 24;
+
+ /** processContent is 'skip' **/
+
+ public static final short CONTENTSPECNODE_ANY_SKIP = 38;
+
+ public static final short CONTENTSPECNODE_ANY_OTHER_SKIP = 39;
+
+ public static final short CONTENTSPECNODE_ANY_LOCAL_SKIP = 40;
+ //
+ // Data
+ //
+
+ /**
+ * The content spec node type.
+ *
+ * @see #CONTENTSPECNODE_LEAF
+ * @see #CONTENTSPECNODE_ZERO_OR_ONE
+ * @see #CONTENTSPECNODE_ZERO_OR_MORE
+ * @see #CONTENTSPECNODE_ONE_OR_MORE
+ * @see #CONTENTSPECNODE_CHOICE
+ * @see #CONTENTSPECNODE_SEQ
+ */
+ public short type;
+
+ /**
+ * The "left hand" value object of the content spec node.
+ * leaf name.localpart, single child for unary ops, left child for binary ops.
+ */
+ public Object value;
+
+ /**
+ * The "right hand" value of the content spec node.
+ * leaf name.uri, right child for binary ops
+ */
+ public Object otherValue;
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XMLContentSpec() {
+ clear();
+ }
+
+ /** Constructs a content spec with the specified values. */
+ public XMLContentSpec(short type, Object value, Object otherValue) {
+ setValues(type, value, otherValue);
+ }
+
+ /**
+ * Constructs a content spec from the values in the specified content spec.
+ */
+ public XMLContentSpec(XMLContentSpec contentSpec) {
+ setValues(contentSpec);
+ }
+
+ /**
+ * Constructs a content spec from the values specified by the given
+ * content spec provider and identifier.
+ */
+ public XMLContentSpec(XMLContentSpec.Provider provider,
+ int contentSpecIndex) {
+ setValues(provider, contentSpecIndex);
+ }
+
+ //
+ // Public methods
+ //
+
+ /** Clears the values. */
+ public void clear() {
+ type = -1;
+ value = null;
+ otherValue = null;
+ }
+
+ /** Sets the values. */
+ public void setValues(short type, Object value, Object otherValue) {
+ this.type = type;
+ this.value = value;
+ this.otherValue = otherValue;
+ }
+
+ /** Sets the values of the specified content spec. */
+ public void setValues(XMLContentSpec contentSpec) {
+ type = contentSpec.type;
+ value = contentSpec.value;
+ otherValue = contentSpec.otherValue;
+ }
+
+ /**
+ * Sets the values from the values specified by the given content spec
+ * provider and identifier. If the specified content spec cannot be
+ * provided, the values of this content spec are cleared.
+ */
+ public void setValues(XMLContentSpec.Provider provider,
+ int contentSpecIndex) {
+ if (!provider.getContentSpec(contentSpecIndex, this)) {
+ clear();
+ }
+ }
+
+
+ //
+ // Object methods
+ //
+
+ /** Returns a hash code for this node. */
+ public int hashCode() {
+ return type << 16 |
+ value.hashCode() << 8 |
+ otherValue.hashCode();
+ }
+
+ /** Returns true if the two objects are equal. */
+ public boolean equals(Object object) {
+ if (object != null && object instanceof XMLContentSpec) {
+ XMLContentSpec contentSpec = (XMLContentSpec)object;
+ return type == contentSpec.type &&
+ value == contentSpec.value &&
+ otherValue == contentSpec.otherValue;
+ }
+ return false;
+ }
+
+
+ //
+ // Interfaces
+ //
+
+ /**
+ * Provides a means for walking the structure built out of
+ * content spec "nodes". The user of this provider interface is
+ * responsible for knowing what the content spec node values
+ * "mean". If those values refer to content spec identifiers,
+ * then the user can call back into the provider to get the
+ * next content spec node in the structure.
+ *
+ * @xerces.internal
+ */
+ public interface Provider {
+
+ //
+ // XMLContentSpec.Provider methods
+ //
+
+ /**
+ * Fills in the provided content spec structure with content spec
+ * information for a unique identifier.
+ *
+ * @param contentSpecIndex The content spec identifier. All content
+ * spec "nodes" have a unique identifier.
+ * @param contentSpec The content spec struct to fill in with
+ * the information.
+ *
+ * @return Returns true if the contentSpecIndex was found.
+ */
+ public boolean getContentSpec(int contentSpecIndex, XMLContentSpec contentSpec);
+
+ } // interface Provider
+
+} // class XMLContentSpec
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDDescription.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDDescription.java
new file mode 100644
index 0000000..0bb366c
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDDescription.java
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+import org.apache.xerces.util.XMLResourceIdentifierImpl;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.grammars.XMLGrammarDescription;
+import org.apache.xerces.xni.parser.XMLInputSource;
+
+/**
+ * All information specific to DTD grammars.
+ *
+ * @xerces.internal
+ *
+ * @author Neil Graham, IBM
+ * @version $Id$
+ */
+public class XMLDTDDescription extends XMLResourceIdentifierImpl
+ implements org.apache.xerces.xni.grammars.XMLDTDDescription {
+
+ // Data
+
+ // pieces of information needed to make this usable as a Grammar key
+ // if we know the root of this grammar, here's its name:
+ protected String fRootName = null;
+
+ // if we don't know the root name, this stores all elements that
+ // could serve; fPossibleRoots and fRootName cannot both be non-null
+ protected ArrayList fPossibleRoots = null;
+
+ // Constructors:
+ public XMLDTDDescription(XMLResourceIdentifier id, String rootName) {
+ this.setValues(id.getPublicId(), id.getLiteralSystemId(),
+ id.getBaseSystemId(), id.getExpandedSystemId());
+ this.fRootName = rootName;
+ this.fPossibleRoots = null;
+ } // init(XMLResourceIdentifier, String)
+
+ public XMLDTDDescription(String publicId, String literalId,
+ String baseId, String expandedId, String rootName) {
+ this.setValues(publicId, literalId, baseId, expandedId);
+ this.fRootName = rootName;
+ this.fPossibleRoots = null;
+ } // init(String, String, String, String, String)
+
+ public XMLDTDDescription(XMLInputSource source) {
+ this.setValues(source.getPublicId(), null,
+ source.getBaseSystemId(), source.getSystemId());
+ this.fRootName = null;
+ this.fPossibleRoots = null;
+ } // init(XMLInputSource)
+
+ // XMLGrammarDescription methods
+
+ public String getGrammarType () {
+ return XMLGrammarDescription.XML_DTD;
+ } // getGrammarType(): String
+
+ /**
+ * @return the root name of this DTD or null if root name is unknown
+ */
+ public String getRootName() {
+ return fRootName;
+ } // getRootName(): String
+
+ /** Set the root name **/
+ public void setRootName(String rootName) {
+ fRootName = rootName;
+ fPossibleRoots = null;
+ }
+
+ /** Set possible roots **/
+ public void setPossibleRoots(ArrayList possibleRoots) {
+ fPossibleRoots = possibleRoots;
+ }
+
+ /** Set possible roots **/
+ public void setPossibleRoots(Vector possibleRoots) {
+ fPossibleRoots = (possibleRoots != null) ? new ArrayList(possibleRoots) : null;
+ }
+
+ /**
+ * Compares this grammar with the given grammar. Currently, we compare
+ * as follows:
+ * - if grammar type not equal return false immediately
+ * - try and find a common root name:
+ * - if both have roots, use them
+ * - else if one has a root, examine other's possible root's for a match;
+ * - else try all combinations
+ * - test fExpandedSystemId and fPublicId as above
+ *
+ * @param desc The description of the grammar to be compared with
+ * @return True if they are equal, else false
+ */
+ public boolean equals(Object desc) {
+ if (!(desc instanceof XMLGrammarDescription)) return false;
+ if (!getGrammarType().equals(((XMLGrammarDescription)desc).getGrammarType())) {
+ return false;
+ }
+ // assume it's a DTDDescription
+ XMLDTDDescription dtdDesc = (XMLDTDDescription)desc;
+ if (fRootName != null) {
+ if ((dtdDesc.fRootName) != null && !dtdDesc.fRootName.equals(fRootName)) {
+ return false;
+ }
+ else if (dtdDesc.fPossibleRoots != null && !dtdDesc.fPossibleRoots.contains(fRootName)) {
+ return false;
+ }
+ }
+ else if (fPossibleRoots != null) {
+ if (dtdDesc.fRootName != null) {
+ if (!fPossibleRoots.contains(dtdDesc.fRootName)) {
+ return false;
+ }
+ }
+ else if (dtdDesc.fPossibleRoots == null) {
+ return false;
+ }
+ else {
+ boolean found = false;
+ final int size = fPossibleRoots.size();
+ for (int i = 0; i < size; ++i) {
+ String root = (String) fPossibleRoots.get(i);
+ found = dtdDesc.fPossibleRoots.contains(root);
+ if (found) break;
+ }
+ if (!found) return false;
+ }
+ }
+ // if we got this far we've got a root match... try other two fields,
+ // since so many different DTD's have roots in common:
+ if (fExpandedSystemId != null) {
+ if (!fExpandedSystemId.equals(dtdDesc.fExpandedSystemId)) {
+ return false;
+ }
+ }
+ else if (dtdDesc.fExpandedSystemId != null) {
+ return false;
+ }
+ if (fPublicId != null) {
+ if (!fPublicId.equals(dtdDesc.fPublicId)) {
+ return false;
+ }
+ }
+ else if (dtdDesc.fPublicId != null) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns the hash code of this grammar
+ * Because our .equals method is so complex, we just return a very
+ * simple hash that might avoid calls to the equals method a bit...
+ * @return The hash code
+ */
+ public int hashCode() {
+ if (fExpandedSystemId != null) {
+ return fExpandedSystemId.hashCode();
+ }
+ if (fPublicId != null) {
+ return fPublicId.hashCode();
+ }
+ // give up; hope .equals can handle it:
+ return 0;
+ }
+} // class XMLDTDDescription
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDLoader.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDLoader.java
new file mode 100644
index 0000000..d547d4a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDLoader.java
@@ -0,0 +1,511 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Locale;
+
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.impl.XMLDTDScannerImpl;
+import org.apache.xerces.impl.XMLEntityManager;
+import org.apache.xerces.impl.XMLErrorReporter;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.DefaultErrorHandler;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.grammars.Grammar;
+import org.apache.xerces.xni.grammars.XMLGrammarLoader;
+import org.apache.xerces.xni.grammars.XMLGrammarPool;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+import org.apache.xerces.xni.parser.XMLErrorHandler;
+import org.apache.xerces.xni.parser.XMLInputSource;
+
+/**
+ * The DTD loader. The loader knows how to build grammars from XMLInputSources.
+ * It extends the DTD processor in order to do this; it's
+ * a separate class because DTD processors don't need to know how
+ * to talk to the outside world in their role as instance-document
+ * helpers.
+ *
+ * This component requires the following features and properties. It
+ * know ho to set them if no one else does:from the
+ *
+ * - http://xml.org/sax/features/namespaces
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/grammar-pool
+ * - http://apache.org/xml/properties/internal/datatype-validator-factory
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Neil Graham, IBM
+ * @author Michael Glavassevich, IBM
+ *
+ * @version $Id$
+ */
+public class XMLDTDLoader
+ extends XMLDTDProcessor
+ implements XMLGrammarLoader {
+
+ //
+ // Constants
+ //
+
+ // feature identifiers
+
+ /** Feature identifier: standard uri conformant feature. */
+ protected static final String STANDARD_URI_CONFORMANT_FEATURE =
+ Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
+
+ /** Feature identifier: balance syntax trees. */
+ protected static final String BALANCE_SYNTAX_TREES =
+ Constants.XERCES_FEATURE_PREFIX + Constants.BALANCE_SYNTAX_TREES;
+
+ // recognized features:
+ private static final String[] LOADER_RECOGNIZED_FEATURES = {
+ VALIDATION,
+ WARN_ON_DUPLICATE_ATTDEF,
+ WARN_ON_UNDECLARED_ELEMDEF,
+ NOTIFY_CHAR_REFS,
+ STANDARD_URI_CONFORMANT_FEATURE,
+ BALANCE_SYNTAX_TREES
+ };
+
+ // property identifiers
+
+ /** Property identifier: error handler. */
+ protected static final String ERROR_HANDLER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
+
+ /** Property identifier: entity resolver. */
+ protected static final String ENTITY_RESOLVER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
+
+ /** Property identifier: locale. */
+ protected static final String LOCALE =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
+
+ /** Recognized properties. */
+ private static final String[] LOADER_RECOGNIZED_PROPERTIES = {
+ SYMBOL_TABLE,
+ ERROR_REPORTER,
+ ERROR_HANDLER,
+ ENTITY_RESOLVER,
+ GRAMMAR_POOL,
+ DTD_VALIDATOR,
+ LOCALE
+ };
+
+ // enforcing strict uri?
+ private boolean fStrictURI = false;
+
+ /** Controls whether the DTD grammar produces balanced syntax trees. */
+ private boolean fBalanceSyntaxTrees = false;
+
+ /** Entity resolver . */
+ protected XMLEntityResolver fEntityResolver;
+
+ // the scanner we use to actually read the DTD
+ protected XMLDTDScannerImpl fDTDScanner;
+
+ // the entity manager the scanner needs.
+ protected XMLEntityManager fEntityManager;
+
+ // what's our Locale?
+ protected Locale fLocale;
+
+ //
+ // Constructors
+ //
+
+ /** Deny default construction; we need a SymtolTable! */
+ public XMLDTDLoader() {
+ this(new SymbolTable());
+ } // ()
+
+ public XMLDTDLoader(SymbolTable symbolTable) {
+ this(symbolTable, null);
+ } // init(SymbolTable)
+
+ public XMLDTDLoader(SymbolTable symbolTable,
+ XMLGrammarPool grammarPool) {
+ this(symbolTable, grammarPool, null, new XMLEntityManager());
+ } // init(SymbolTable, XMLGrammarPool)
+
+ XMLDTDLoader(SymbolTable symbolTable,
+ XMLGrammarPool grammarPool, XMLErrorReporter errorReporter,
+ XMLEntityResolver entityResolver) {
+ fSymbolTable = symbolTable;
+ fGrammarPool = grammarPool;
+ if(errorReporter == null) {
+ errorReporter = new XMLErrorReporter();
+ errorReporter.setProperty(ERROR_HANDLER, new DefaultErrorHandler());
+ }
+ fErrorReporter = errorReporter;
+ // Add XML message formatter if there isn't one.
+ if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
+ XMLMessageFormatter xmft = new XMLMessageFormatter();
+ fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
+ fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
+ }
+ fEntityResolver = entityResolver;
+ if(fEntityResolver instanceof XMLEntityManager) {
+ fEntityManager = (XMLEntityManager)fEntityResolver;
+ } else {
+ fEntityManager = new XMLEntityManager();
+ }
+ fEntityManager.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY, errorReporter);
+ fDTDScanner = createDTDScanner(fSymbolTable, fErrorReporter, fEntityManager);
+ fDTDScanner.setDTDHandler(this);
+ fDTDScanner.setDTDContentModelHandler(this);
+ reset();
+ } // init(SymbolTable, XMLGrammarPool, XMLErrorReporter, XMLEntityResolver)
+
+ // XMLGrammarLoader methods
+
+ /**
+ * Returns a list of feature identifiers that are recognized by
+ * this component. This method may return null if no features
+ * are recognized by this component.
+ */
+ public String[] getRecognizedFeatures() {
+ return (String[])(LOADER_RECOGNIZED_FEATURES.clone());
+ } // getRecognizedFeatures():String[]
+
+ /**
+ * Sets the state of a feature. This method is called by the component
+ * manager any time after reset when a feature changes state.
+ *
+ * Note: Components should silently ignore features
+ * that do not affect the operation of the component.
+ *
+ * @param featureId The feature identifier.
+ * @param state The state of the feature.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setFeature(String featureId, boolean state)
+ throws XMLConfigurationException {
+ if (featureId.equals(VALIDATION)) {
+ fValidation = state;
+ }
+ else if (featureId.equals(WARN_ON_DUPLICATE_ATTDEF)) {
+ fWarnDuplicateAttdef = state;
+ }
+ else if (featureId.equals(WARN_ON_UNDECLARED_ELEMDEF)) {
+ fWarnOnUndeclaredElemdef = state;
+ }
+ else if (featureId.equals(NOTIFY_CHAR_REFS)) {
+ fDTDScanner.setFeature(featureId, state);
+ }
+ else if (featureId.equals(STANDARD_URI_CONFORMANT_FEATURE)) {
+ fStrictURI = state;
+ }
+ else if (featureId.equals(BALANCE_SYNTAX_TREES)) {
+ fBalanceSyntaxTrees = state;
+ }
+ else {
+ throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, featureId);
+ }
+ } // setFeature(String,boolean)
+
+ /**
+ * Returns a list of property identifiers that are recognized by
+ * this component. This method may return null if no properties
+ * are recognized by this component.
+ */
+ public String[] getRecognizedProperties() {
+ return (String[])(LOADER_RECOGNIZED_PROPERTIES.clone());
+ } // getRecognizedProperties():String[]
+
+ /**
+ * Returns the state of a property.
+ *
+ * @param propertyId The property identifier.
+ *
+ * @throws XMLConfigurationException Thrown on configuration error.
+ */
+ public Object getProperty(String propertyId)
+ throws XMLConfigurationException {
+ if (propertyId.equals(SYMBOL_TABLE)) {
+ return fSymbolTable;
+ }
+ else if (propertyId.equals(ERROR_REPORTER)) {
+ return fErrorReporter;
+ }
+ else if (propertyId.equals(ERROR_HANDLER)) {
+ return fErrorReporter.getErrorHandler();
+ }
+ else if (propertyId.equals(ENTITY_RESOLVER)) {
+ return fEntityResolver;
+ }
+ else if (propertyId.equals(LOCALE)) {
+ return getLocale();
+ }
+ else if (propertyId.equals(GRAMMAR_POOL)) {
+ return fGrammarPool;
+ }
+ else if (propertyId.equals(DTD_VALIDATOR)) {
+ return fValidator;
+ }
+ throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, propertyId);
+ } // getProperty(String): Object
+
+ /**
+ * Sets the value of a property. This method is called by the component
+ * manager any time after reset when a property changes value.
+ *
+ * Note: Components should silently ignore properties
+ * that do not affect the operation of the component.
+ *
+ * @param propertyId The property identifier.
+ * @param value The value of the property.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setProperty(String propertyId, Object value)
+ throws XMLConfigurationException {
+ if (propertyId.equals(SYMBOL_TABLE)) {
+ fSymbolTable = (SymbolTable)value;
+ fDTDScanner.setProperty(propertyId, value);
+ fEntityManager.setProperty(propertyId, value);
+ }
+ else if(propertyId.equals(ERROR_REPORTER)) {
+ fErrorReporter = (XMLErrorReporter)value;
+ // Add XML message formatter if there isn't one.
+ if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
+ XMLMessageFormatter xmft = new XMLMessageFormatter();
+ fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
+ fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
+ }
+ fDTDScanner.setProperty(propertyId, value);
+ fEntityManager.setProperty(propertyId, value);
+ }
+ else if (propertyId.equals(ERROR_HANDLER)) {
+ fErrorReporter.setProperty(propertyId, value);
+ }
+ else if (propertyId.equals(ENTITY_RESOLVER)) {
+ fEntityResolver = (XMLEntityResolver)value;
+ fEntityManager.setProperty(propertyId, value);
+ }
+ else if (propertyId.equals(LOCALE)) {
+ setLocale((Locale) value);
+ }
+ else if(propertyId.equals(GRAMMAR_POOL)) {
+ fGrammarPool = (XMLGrammarPool)value;
+ }
+ else {
+ throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, propertyId);
+ }
+ } // setProperty(String,Object)
+
+ /**
+ * Returns the state of a feature.
+ *
+ * @param featureId The feature identifier.
+ *
+ * @throws XMLConfigurationException Thrown on configuration error.
+ */
+ public boolean getFeature(String featureId)
+ throws XMLConfigurationException {
+ if (featureId.equals(VALIDATION)) {
+ return fValidation;
+ }
+ else if (featureId.equals(WARN_ON_DUPLICATE_ATTDEF)) {
+ return fWarnDuplicateAttdef;
+ }
+ else if (featureId.equals(WARN_ON_UNDECLARED_ELEMDEF)) {
+ return fWarnOnUndeclaredElemdef;
+ }
+ else if (featureId.equals(NOTIFY_CHAR_REFS)) {
+ return fDTDScanner.getFeature(featureId);
+ }
+ else if (featureId.equals(STANDARD_URI_CONFORMANT_FEATURE)) {
+ return fStrictURI;
+ }
+ else if (featureId.equals(BALANCE_SYNTAX_TREES)) {
+ return fBalanceSyntaxTrees;
+ }
+ throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, featureId);
+ } //getFeature(String): boolean
+
+ /**
+ * Set the locale to use for messages.
+ *
+ * @param locale The locale object to use for localization of messages.
+ *
+ * @exception XNIException Thrown if the parser does not support the
+ * specified locale.
+ */
+ public void setLocale(Locale locale) {
+ fLocale = locale;
+ fErrorReporter.setLocale(locale);
+ } // setLocale(Locale)
+
+ /** Return the Locale the XMLGrammarLoader is using. */
+ public Locale getLocale() {
+ return fLocale;
+ } // getLocale(): Locale
+
+
+ /**
+ * Sets the error handler.
+ *
+ * @param errorHandler The error handler.
+ */
+ public void setErrorHandler(XMLErrorHandler errorHandler) {
+ fErrorReporter.setProperty(ERROR_HANDLER, errorHandler);
+ } // setErrorHandler(XMLErrorHandler)
+
+ /** Returns the registered error handler. */
+ public XMLErrorHandler getErrorHandler() {
+ return fErrorReporter.getErrorHandler();
+ } // getErrorHandler(): XMLErrorHandler
+
+ /**
+ * Sets the entity resolver.
+ *
+ * @param entityResolver The new entity resolver.
+ */
+ public void setEntityResolver(XMLEntityResolver entityResolver) {
+ fEntityResolver = entityResolver;
+ fEntityManager.setProperty(ENTITY_RESOLVER, entityResolver);
+ } // setEntityResolver(XMLEntityResolver)
+
+ /** Returns the registered entity resolver. */
+ public XMLEntityResolver getEntityResolver() {
+ return fEntityResolver;
+ } // getEntityResolver(): XMLEntityResolver
+
+ /**
+ * Returns a Grammar object by parsing the contents of the
+ * entity pointed to by source.
+ *
+ * @param source the location of the entity which forms
+ * the starting point of the grammar to be constructed.
+ * @throws IOException When a problem is encountered reading the entity
+ * XNIException When a condition arises (such as a FatalError) that requires parsing
+ * of the entity be terminated.
+ */
+ public Grammar loadGrammar(XMLInputSource source)
+ throws IOException, XNIException {
+ reset();
+ // First chance checking strict URI
+ String eid = XMLEntityManager.expandSystemId(source.getSystemId(), source.getBaseSystemId(), fStrictURI);
+ XMLDTDDescription desc = new XMLDTDDescription(source.getPublicId(), source.getSystemId(), source.getBaseSystemId(), eid, null);
+ if (!fBalanceSyntaxTrees) {
+ fDTDGrammar = new DTDGrammar(fSymbolTable, desc);
+ }
+ else {
+ fDTDGrammar = new BalancedDTDGrammar(fSymbolTable, desc);
+ }
+ fGrammarBucket = new DTDGrammarBucket();
+ fGrammarBucket.setStandalone(false);
+ fGrammarBucket.setActiveGrammar(fDTDGrammar);
+ // no reason to use grammar bucket's "put" method--we
+ // know which grammar it is, and we don't know the root name anyway...
+
+ // actually start the parsing!
+ try {
+ fDTDScanner.setInputSource(source);
+ fDTDScanner.scanDTDExternalSubset(true);
+ } catch (EOFException e) {
+ // expected behaviour...
+ }
+ finally {
+ // Close all streams opened by the parser.
+ fEntityManager.closeReaders();
+ }
+ if(fDTDGrammar != null && fGrammarPool != null) {
+ fGrammarPool.cacheGrammars(XMLDTDDescription.XML_DTD, new Grammar[] {fDTDGrammar});
+ }
+ return fDTDGrammar;
+ } // loadGrammar(XMLInputSource): Grammar
+
+ /**
+ * Parse a DTD internal and/or external subset and insert the content
+ * into the existing DTD grammar owned by the given DTDValidator.
+ */
+ public void loadGrammarWithContext(XMLDTDValidator validator, String rootName,
+ String publicId, String systemId, String baseSystemId, String internalSubset)
+ throws IOException, XNIException {
+ final DTDGrammarBucket grammarBucket = validator.getGrammarBucket();
+ final DTDGrammar activeGrammar = grammarBucket.getActiveGrammar();
+ if (activeGrammar != null && !activeGrammar.isImmutable()) {
+ fGrammarBucket = grammarBucket;
+ fEntityManager.setScannerVersion(getScannerVersion());
+ reset();
+ try {
+ // process internal subset
+ if (internalSubset != null) {
+ // To get the DTD scanner to end at the right place we have to fool
+ // it into thinking that it reached the end of the internal subset
+ // in a real document.
+ StringBuffer buffer = new StringBuffer(internalSubset.length() + 2);
+ buffer.append(internalSubset).append("]>");
+ XMLInputSource is = new XMLInputSource(null, baseSystemId,
+ null, new StringReader(buffer.toString()), null);
+ fEntityManager.startDocumentEntity(is);
+ fDTDScanner.scanDTDInternalSubset(true, false, systemId != null);
+ }
+ // process external subset
+ if (systemId != null) {
+ XMLDTDDescription desc = new XMLDTDDescription(publicId, systemId, baseSystemId, null, rootName);
+ XMLInputSource source = fEntityManager.resolveEntity(desc);
+ fDTDScanner.setInputSource(source);
+ fDTDScanner.scanDTDExternalSubset(true);
+ }
+ }
+ catch (EOFException e) {
+ // expected behaviour...
+ }
+ finally {
+ // Close all streams opened by the parser.
+ fEntityManager.closeReaders();
+ }
+ }
+ } // loadGrammarWithContext(XMLDTDValidator, String, String, String, String, String)
+
+ // reset all the components that we rely upon
+ protected void reset() {
+ super.reset();
+ fDTDScanner.reset();
+ fEntityManager.reset();
+ fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
+ }
+
+ protected XMLDTDScannerImpl createDTDScanner(SymbolTable symbolTable,
+ XMLErrorReporter errorReporter, XMLEntityManager entityManager) {
+ return new XMLDTDScannerImpl(symbolTable, errorReporter, entityManager);
+ } // createDTDScanner(SymbolTable, XMLErrorReporter, XMLEntityManager) : XMLDTDScannerImpl
+
+ protected short getScannerVersion() {
+ return Constants.XML_VERSION_1_0;
+ } // getScannerVersion() : short
+
+} // class XMLDTDLoader
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDProcessor.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDProcessor.java
new file mode 100644
index 0000000..e452983
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDProcessor.java
@@ -0,0 +1,1735 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.impl.XMLErrorReporter;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.XMLDTDContentModelHandler;
+import org.apache.xerces.xni.XMLDTDHandler;
+import org.apache.xerces.xni.XMLLocator;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.grammars.Grammar;
+import org.apache.xerces.xni.grammars.XMLGrammarDescription;
+import org.apache.xerces.xni.grammars.XMLGrammarPool;
+import org.apache.xerces.xni.parser.XMLComponent;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLDTDContentModelFilter;
+import org.apache.xerces.xni.parser.XMLDTDContentModelSource;
+import org.apache.xerces.xni.parser.XMLDTDFilter;
+import org.apache.xerces.xni.parser.XMLDTDSource;
+
+/**
+ * The DTD processor. The processor implements a DTD
+ * filter: receiving DTD events from the DTD scanner; validating
+ * the content and structure; building a grammar, if applicable;
+ * and notifying the DTDHandler of the information resulting from the
+ * process.
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/namespaces
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/grammar-pool
+ * - http://apache.org/xml/properties/internal/datatype-validator-factory
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Neil Graham, IBM
+ *
+ * @version $Id$
+ */
+public class XMLDTDProcessor
+ implements XMLComponent, XMLDTDFilter, XMLDTDContentModelFilter {
+
+ //
+ // Constants
+ //
+
+ /** Top level scope (-1). */
+ private static final int TOP_LEVEL_SCOPE = -1;
+
+ // feature identifiers
+
+ /** Feature identifier: validation. */
+ protected static final String VALIDATION =
+ Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
+
+ /** Feature identifier: notify character references. */
+ protected static final String NOTIFY_CHAR_REFS =
+ Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_CHAR_REFS_FEATURE;
+
+ /** Feature identifier: warn on duplicate attdef */
+ protected static final String WARN_ON_DUPLICATE_ATTDEF =
+ Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
+
+ /** Feature identifier: warn on undeclared element referenced in content model. */
+ protected static final String WARN_ON_UNDECLARED_ELEMDEF =
+ Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_UNDECLARED_ELEMDEF_FEATURE;
+
+ protected static final String PARSER_SETTINGS =
+ Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
+
+ // property identifiers
+
+ /** Property identifier: symbol table. */
+ protected static final String SYMBOL_TABLE =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
+
+ /** Property identifier: error reporter. */
+ protected static final String ERROR_REPORTER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
+
+ /** Property identifier: grammar pool. */
+ protected static final String GRAMMAR_POOL =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
+
+ /** Property identifier: validator . */
+ protected static final String DTD_VALIDATOR =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
+
+ // recognized features and properties
+
+ /** Recognized features. */
+ private static final String[] RECOGNIZED_FEATURES = {
+ VALIDATION,
+ WARN_ON_DUPLICATE_ATTDEF,
+ WARN_ON_UNDECLARED_ELEMDEF,
+ NOTIFY_CHAR_REFS,
+ };
+
+ /** Feature defaults. */
+ private static final Boolean[] FEATURE_DEFAULTS = {
+ null,
+ Boolean.FALSE,
+ Boolean.FALSE,
+ null,
+ };
+
+ /** Recognized properties. */
+ private static final String[] RECOGNIZED_PROPERTIES = {
+ SYMBOL_TABLE,
+ ERROR_REPORTER,
+ GRAMMAR_POOL,
+ DTD_VALIDATOR,
+ };
+
+ /** Property defaults. */
+ private static final Object[] PROPERTY_DEFAULTS = {
+ null,
+ null,
+ null,
+ null,
+ };
+
+ // debugging
+
+ //
+ // Data
+ //
+
+ // features
+
+ /** Validation. */
+ protected boolean fValidation;
+
+ /** Validation against only DTD */
+ protected boolean fDTDValidation;
+
+ /** warn on duplicate attribute definition, this feature works only when validation is true */
+ protected boolean fWarnDuplicateAttdef;
+
+ /** warn on undeclared element referenced in content model, this feature only works when valiation is true */
+ protected boolean fWarnOnUndeclaredElemdef;
+
+ // properties
+
+ /** Symbol table. */
+ protected SymbolTable fSymbolTable;
+
+ /** Error reporter. */
+ protected XMLErrorReporter fErrorReporter;
+
+ /** Grammar bucket. */
+ protected DTDGrammarBucket fGrammarBucket;
+
+ // the validator to which we look for our grammar bucket (the
+ // validator needs to hold the bucket so that it can initialize
+ // the grammar with details like whether it's for a standalone document...
+ protected XMLDTDValidator fValidator;
+
+ // the grammar pool we'll try to add the grammar to:
+ protected XMLGrammarPool fGrammarPool;
+
+ // what's our Locale?
+ protected Locale fLocale;
+
+ // handlers
+
+ /** DTD handler. */
+ protected XMLDTDHandler fDTDHandler;
+
+ /** DTD source. */
+ protected XMLDTDSource fDTDSource;
+
+ /** DTD content model handler. */
+ protected XMLDTDContentModelHandler fDTDContentModelHandler;
+
+ /** DTD content model source. */
+ protected XMLDTDContentModelSource fDTDContentModelSource;
+
+ // grammars
+
+ /** DTD Grammar. */
+ protected DTDGrammar fDTDGrammar;
+
+ // state
+
+ /** Perform validation. */
+ private boolean fPerformValidation;
+
+ /** True if in an ignore conditional section of the DTD. */
+ protected boolean fInDTDIgnore;
+
+ // information regarding the current element
+
+ // validation states
+
+ /** Mixed. */
+ private boolean fMixed;
+
+ // temporary variables
+
+ /** Temporary entity declaration. */
+ private final XMLEntityDecl fEntityDecl = new XMLEntityDecl();
+
+ /** Notation declaration hash. */
+ private final HashMap fNDataDeclNotations = new HashMap();
+
+ /** DTD element declaration name. */
+ private String fDTDElementDeclName = null;
+
+ /** Mixed element type "hash". */
+ private final ArrayList fMixedElementTypes = new ArrayList();
+
+ /** Element declarations in DTD. */
+ private final ArrayList fDTDElementDecls = new ArrayList();
+
+ // to check for duplicate ID or ANNOTATION attribute declare in
+ // ATTLIST, and misc VCs
+
+ /** ID attribute names. */
+ private HashMap fTableOfIDAttributeNames;
+
+ /** NOTATION attribute names. */
+ private HashMap fTableOfNOTATIONAttributeNames;
+
+ /** NOTATION enumeration values. */
+ private HashMap fNotationEnumVals;
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XMLDTDProcessor() {
+
+ // initialize data
+
+ } // ()
+
+ //
+ // XMLComponent methods
+ //
+
+ /*
+ * Resets the component. The component can query the component manager
+ * about any features and properties that affect the operation of the
+ * component.
+ *
+ * @param componentManager The component manager.
+ *
+ * @throws SAXException Thrown by component on finitialization error.
+ * For example, if a feature or property is
+ * required for the operation of the component, the
+ * component manager may throw a
+ * SAXNotRecognizedException or a
+ * SAXNotSupportedException.
+ */
+ public void reset(XMLComponentManager componentManager) throws XMLConfigurationException {
+
+ boolean parser_settings;
+ try {
+ parser_settings = componentManager.getFeature(PARSER_SETTINGS);
+ } catch (XMLConfigurationException e) {
+ parser_settings = true;
+ }
+
+ if (!parser_settings) {
+ // parser settings have not been changed
+ reset();
+ return;
+ }
+
+ // sax features
+ try {
+ fValidation = componentManager.getFeature(VALIDATION);
+ } catch (XMLConfigurationException e) {
+ fValidation = false;
+ }
+ try {
+ fDTDValidation =
+ !(componentManager
+ .getFeature(
+ Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE));
+ } catch (XMLConfigurationException e) {
+ // must be in a schema-less configuration!
+ fDTDValidation = true;
+ }
+
+ // Xerces features
+
+ try {
+ fWarnDuplicateAttdef = componentManager.getFeature(WARN_ON_DUPLICATE_ATTDEF);
+ }
+ catch (XMLConfigurationException e) {
+ fWarnDuplicateAttdef = false;
+ }
+ try {
+ fWarnOnUndeclaredElemdef = componentManager.getFeature(WARN_ON_UNDECLARED_ELEMDEF);
+ }
+ catch (XMLConfigurationException e) {
+ fWarnOnUndeclaredElemdef = false;
+ }
+
+ // get needed components
+ fErrorReporter =
+ (XMLErrorReporter) componentManager.getProperty(
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY);
+ fSymbolTable =
+ (SymbolTable) componentManager.getProperty(
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY);
+ try {
+ fGrammarPool = (XMLGrammarPool) componentManager.getProperty(GRAMMAR_POOL);
+ } catch (XMLConfigurationException e) {
+ fGrammarPool = null;
+ }
+ try {
+ fValidator = (XMLDTDValidator) componentManager.getProperty(DTD_VALIDATOR);
+ } catch (XMLConfigurationException e) {
+ fValidator = null;
+ } catch (ClassCastException e) {
+ fValidator = null;
+ }
+ // we get our grammarBucket from the validator...
+ if (fValidator != null) {
+ fGrammarBucket = fValidator.getGrammarBucket();
+ } else {
+ fGrammarBucket = null;
+ }
+ reset();
+
+ } // reset(XMLComponentManager)
+
+ protected void reset() {
+ // clear grammars
+ fDTDGrammar = null;
+ // initialize state
+ fInDTDIgnore = false;
+
+ fNDataDeclNotations.clear();
+
+ // datatype validators
+ if (fValidation) {
+
+ if (fNotationEnumVals == null) {
+ fNotationEnumVals = new HashMap();
+ }
+ fNotationEnumVals.clear();
+
+ fTableOfIDAttributeNames = new HashMap();
+ fTableOfNOTATIONAttributeNames = new HashMap();
+ }
+
+ }
+ /**
+ * Returns a list of feature identifiers that are recognized by
+ * this component. This method may return null if no features
+ * are recognized by this component.
+ */
+ public String[] getRecognizedFeatures() {
+ return (String[])(RECOGNIZED_FEATURES.clone());
+ } // getRecognizedFeatures():String[]
+
+ /**
+ * Sets the state of a feature. This method is called by the component
+ * manager any time after reset when a feature changes state.
+ *
+ * Note: Components should silently ignore features
+ * that do not affect the operation of the component.
+ *
+ * @param featureId The feature identifier.
+ * @param state The state of the feature.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setFeature(String featureId, boolean state)
+ throws XMLConfigurationException {
+ } // setFeature(String,boolean)
+
+ /**
+ * Returns a list of property identifiers that are recognized by
+ * this component. This method may return null if no properties
+ * are recognized by this component.
+ */
+ public String[] getRecognizedProperties() {
+ return (String[])(RECOGNIZED_PROPERTIES.clone());
+ } // getRecognizedProperties():String[]
+
+ /**
+ * Sets the value of a property. This method is called by the component
+ * manager any time after reset when a property changes value.
+ *
+ * Note: Components should silently ignore properties
+ * that do not affect the operation of the component.
+ *
+ * @param propertyId The property identifier.
+ * @param value The value of the property.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setProperty(String propertyId, Object value)
+ throws XMLConfigurationException {
+ } // setProperty(String,Object)
+
+ /**
+ * Returns the default state for a feature, or null if this
+ * component does not want to report a default value for this
+ * feature.
+ *
+ * @param featureId The feature identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Boolean getFeatureDefault(String featureId) {
+ for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
+ if (RECOGNIZED_FEATURES[i].equals(featureId)) {
+ return FEATURE_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getFeatureDefault(String):Boolean
+
+ /**
+ * Returns the default state for a property, or null if this
+ * component does not want to report a default value for this
+ * property.
+ *
+ * @param propertyId The property identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Object getPropertyDefault(String propertyId) {
+ for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
+ if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
+ return PROPERTY_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getPropertyDefault(String):Object
+
+ //
+ // XMLDTDSource methods
+ //
+
+ /**
+ * Sets the DTD handler.
+ *
+ * @param dtdHandler The DTD handler.
+ */
+ public void setDTDHandler(XMLDTDHandler dtdHandler) {
+ fDTDHandler = dtdHandler;
+ } // setDTDHandler(XMLDTDHandler)
+
+ /**
+ * Returns the DTD handler.
+ *
+ * @return The DTD handler.
+ */
+ public XMLDTDHandler getDTDHandler() {
+ return fDTDHandler;
+ } // getDTDHandler(): XMLDTDHandler
+
+ //
+ // XMLDTDContentModelSource methods
+ //
+
+ /**
+ * Sets the DTD content model handler.
+ *
+ * @param dtdContentModelHandler The DTD content model handler.
+ */
+ public void setDTDContentModelHandler(XMLDTDContentModelHandler dtdContentModelHandler) {
+ fDTDContentModelHandler = dtdContentModelHandler;
+ } // setDTDContentModelHandler(XMLDTDContentModelHandler)
+
+ /**
+ * Gets the DTD content model handler.
+ *
+ * @return dtdContentModelHandler The DTD content model handler.
+ */
+ public XMLDTDContentModelHandler getDTDContentModelHandler() {
+ return fDTDContentModelHandler;
+ } // getDTDContentModelHandler(): XMLDTDContentModelHandler
+
+ //
+ // XMLDTDContentModelHandler and XMLDTDHandler methods
+ //
+
+ /**
+ * The start of the DTD external subset.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startExternalSubset(XMLResourceIdentifier identifier,
+ Augmentations augs) throws XNIException {
+ if(fDTDGrammar != null)
+ fDTDGrammar.startExternalSubset(identifier, augs);
+ if(fDTDHandler != null){
+ fDTDHandler.startExternalSubset(identifier, augs);
+ }
+ }
+
+ /**
+ * The end of the DTD external subset.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endExternalSubset(Augmentations augs) throws XNIException {
+ if(fDTDGrammar != null)
+ fDTDGrammar.endExternalSubset(augs);
+ if(fDTDHandler != null){
+ fDTDHandler.endExternalSubset(augs);
+ }
+ }
+
+ /**
+ * Check standalone entity reference.
+ * Made static to make common between the validator and loader.
+ *
+ * @param name
+ *@param grammar grammar to which entity belongs
+ * @param tempEntityDecl empty entity declaration to put results in
+ * @param errorReporter error reporter to send errors to
+ *
+ * @throws XNIException Thrown by application to signal an error.
+ */
+ protected static void checkStandaloneEntityRef(String name, DTDGrammar grammar,
+ XMLEntityDecl tempEntityDecl, XMLErrorReporter errorReporter) throws XNIException {
+ // check VC: Standalone Document Declartion, entities references appear in the document.
+ int entIndex = grammar.getEntityDeclIndex(name);
+ if (entIndex > -1) {
+ grammar.getEntityDecl(entIndex, tempEntityDecl);
+ if (tempEntityDecl.inExternal) {
+ errorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
+ "MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
+ new Object[]{name}, XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ }
+
+ /**
+ * A comment.
+ *
+ * @param text The text in the comment.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by application to signal an error.
+ */
+ public void comment(XMLString text, Augmentations augs) throws XNIException {
+
+ // call handlers
+ if(fDTDGrammar != null)
+ fDTDGrammar.comment(text, augs);
+ if (fDTDHandler != null) {
+ fDTDHandler.comment(text, augs);
+ }
+
+ } // comment(XMLString)
+
+
+ /**
+ * A processing instruction. Processing instructions consist of a
+ * target name and, optionally, text data. The data is only meaningful
+ * to the application.
+ *
+ * Typically, a processing instruction's data will contain a series
+ * of pseudo-attributes. These pseudo-attributes follow the form of
+ * element attributes but are not parsed or presented
+ * to the application as anything other than text. The application is
+ * responsible for parsing the data.
+ *
+ * @param target The target.
+ * @param data The data or null if none specified.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void processingInstruction(String target, XMLString data, Augmentations augs)
+ throws XNIException {
+
+ // call handlers
+ if(fDTDGrammar != null)
+ fDTDGrammar.processingInstruction(target, data, augs);
+ if (fDTDHandler != null) {
+ fDTDHandler.processingInstruction(target, data, augs);
+ }
+ } // processingInstruction(String,XMLString)
+
+ //
+ // XMLDTDHandler methods
+ //
+
+ /**
+ * The start of the DTD.
+ *
+ * @param locator The document locator, or null if the document
+ * location cannot be reported during the parsing of
+ * the document DTD. However, it is strongly
+ * recommended that a locator be supplied that can
+ * at least report the base system identifier of the
+ * DTD.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException {
+
+
+ // initialize state
+ fNDataDeclNotations.clear();
+ fDTDElementDecls.clear();
+
+ // the grammar bucket's DTDGrammar will now be the
+ // one we want, whether we're constructing it or not.
+ // if we're not constructing it, then we should not have a reference
+ // to it!
+ if( !fGrammarBucket.getActiveGrammar().isImmutable()) {
+ fDTDGrammar = fGrammarBucket.getActiveGrammar();
+ }
+
+ // call handlers
+ if(fDTDGrammar != null )
+ fDTDGrammar.startDTD(locator, augs);
+ if (fDTDHandler != null) {
+ fDTDHandler.startDTD(locator, augs);
+ }
+
+ } // startDTD(XMLLocator)
+
+ /**
+ * Characters within an IGNORE conditional section.
+ *
+ * @param text The ignored text.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void ignoredCharacters(XMLString text, Augmentations augs) throws XNIException {
+
+ // ignored characters in DTD
+ if(fDTDGrammar != null )
+ fDTDGrammar.ignoredCharacters(text, augs);
+ if (fDTDHandler != null) {
+ fDTDHandler.ignoredCharacters(text, augs);
+ }
+ }
+
+ /**
+ * Notifies of the presence of a TextDecl line in an entity. If present,
+ * this method will be called immediately following the startParameterEntity call.
+ *
+ * Note: This method is only called for external
+ * parameter entities referenced in the DTD.
+ *
+ * @param version The XML version, or null if not specified.
+ * @param encoding The IANA encoding name of the entity.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
+
+ // call handlers
+ if(fDTDGrammar != null )
+ fDTDGrammar.textDecl(version, encoding, augs);
+ if (fDTDHandler != null) {
+ fDTDHandler.textDecl(version, encoding, augs);
+ }
+ }
+
+ /**
+ * This method notifies of the start of a parameter entity. The parameter
+ * entity name start with a '%' character.
+ *
+ * @param name The name of the parameter entity.
+ * @param identifier The resource identifier.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal parameter entities).
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startParameterEntity(String name,
+ XMLResourceIdentifier identifier,
+ String encoding,
+ Augmentations augs) throws XNIException {
+
+ if (fPerformValidation && fDTDGrammar != null &&
+ fGrammarBucket.getStandalone()) {
+ checkStandaloneEntityRef(name, fDTDGrammar, fEntityDecl, fErrorReporter);
+ }
+ // call handlers
+ if(fDTDGrammar != null )
+ fDTDGrammar.startParameterEntity(name, identifier, encoding, augs);
+ if (fDTDHandler != null) {
+ fDTDHandler.startParameterEntity(name, identifier, encoding, augs);
+ }
+ }
+
+ /**
+ * This method notifies the end of a parameter entity. Parameter entity
+ * names begin with a '%' character.
+ *
+ * @param name The name of the parameter entity.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endParameterEntity(String name, Augmentations augs) throws XNIException {
+
+ // call handlers
+ if(fDTDGrammar != null )
+ fDTDGrammar.endParameterEntity(name, augs);
+ if (fDTDHandler != null) {
+ fDTDHandler.endParameterEntity(name, augs);
+ }
+ }
+
+ /**
+ * An element declaration.
+ *
+ * @param name The name of the element.
+ * @param contentModel The element content model.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void elementDecl(String name, String contentModel, Augmentations augs)
+ throws XNIException {
+
+ //check VC: Unique Element Declaration
+ if (fValidation) {
+ if (fDTDElementDecls.contains(name)) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_ELEMENT_ALREADY_DECLARED",
+ new Object[]{ name},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ else {
+ fDTDElementDecls.add(name);
+ }
+ }
+
+ // call handlers
+ if(fDTDGrammar != null )
+ fDTDGrammar.elementDecl(name, contentModel, augs);
+ if (fDTDHandler != null) {
+ fDTDHandler.elementDecl(name, contentModel, augs);
+ }
+
+ } // elementDecl(String,String)
+
+ /**
+ * The start of an attribute list.
+ *
+ * @param elementName The name of the element that this attribute
+ * list is associated with.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startAttlist(String elementName, Augmentations augs)
+ throws XNIException {
+
+ // call handlers
+ if(fDTDGrammar != null )
+ fDTDGrammar.startAttlist(elementName, augs);
+ if (fDTDHandler != null) {
+ fDTDHandler.startAttlist(elementName, augs);
+ }
+
+ } // startAttlist(String)
+
+ /**
+ * An attribute declaration.
+ *
+ * @param elementName The name of the element that this attribute
+ * is associated with.
+ * @param attributeName The name of the attribute.
+ * @param type The attribute type. This value will be one of
+ * the following: "CDATA", "ENTITY", "ENTITIES",
+ * "ENUMERATION", "ID", "IDREF", "IDREFS",
+ * "NMTOKEN", "NMTOKENS", or "NOTATION".
+ * @param enumeration If the type has the value "ENUMERATION" or
+ * "NOTATION", this array holds the allowed attribute
+ * values; otherwise, this array is null.
+ * @param defaultType The attribute default type. This value will be
+ * one of the following: "#FIXED", "#IMPLIED",
+ * "#REQUIRED", or null.
+ * @param defaultValue The attribute default value, or null if no
+ * default value is specified.
+ * @param nonNormalizedDefaultValue The attribute default value with no normalization
+ * performed, or null if no default value is specified.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void attributeDecl(String elementName, String attributeName,
+ String type, String[] enumeration,
+ String defaultType, XMLString defaultValue,
+ XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
+
+ if (type != XMLSymbols.fCDATASymbol && defaultValue != null) {
+ normalizeDefaultAttrValue(defaultValue);
+ }
+
+ if (fValidation) {
+
+ boolean duplicateAttributeDef = false ;
+
+ //Get Grammar index to grammar array
+ DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar:fGrammarBucket.getActiveGrammar());
+ int elementIndex = grammar.getElementDeclIndex( elementName);
+ if (grammar.getAttributeDeclIndex(elementIndex, attributeName) != -1) {
+ //more than one attribute definition is provided for the same attribute of a given element type.
+ duplicateAttributeDef = true ;
+
+ //this feature works only when validation is true.
+ if(fWarnDuplicateAttdef){
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_DUPLICATE_ATTRIBUTE_DEFINITION",
+ new Object[]{ elementName, attributeName },
+ XMLErrorReporter.SEVERITY_WARNING );
+ }
+ }
+
+
+ //
+ // a) VC: One ID per Element Type, If duplicate ID attribute
+ // b) VC: ID attribute Default. if there is a declareared attribute
+ // default for ID it should be of type #IMPLIED or #REQUIRED
+ if (type == XMLSymbols.fIDSymbol) {
+ if (defaultValue != null && defaultValue.length != 0) {
+ if (defaultType == null ||
+ !(defaultType == XMLSymbols.fIMPLIEDSymbol ||
+ defaultType == XMLSymbols.fREQUIREDSymbol)) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "IDDefaultTypeInvalid",
+ new Object[]{ attributeName},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+
+ if (!fTableOfIDAttributeNames.containsKey(elementName)) {
+ fTableOfIDAttributeNames.put(elementName, attributeName);
+ }
+ else {
+ //we should not report an error, when there is duplicate attribute definition for given element type
+ //according to XML 1.0 spec, When more than one definition is provided for the same attribute of a given
+ //element type, the first declaration is binding and later declaration are *ignored*. So processor should
+ //ignore the second declarations, however an application would be warned of the duplicate attribute defintion
+ // if http://apache.org/xml/features/validation/warn-on-duplicate-attdef feature is set to true,
+ // one typical case where this could be a problem, when any XML file
+ // provide the ID type information through internal subset so that it is available to the parser which read
+ //only internal subset. Now that attribute declaration(ID Type) can again be part of external parsed entity
+ //referenced. At that time if parser doesn't make this distinction it will throw an error for VC One ID per
+ //Element Type, which (second defintion) actually should be ignored. Application behavior may differ on the
+ //basis of error or warning thrown. - nb.
+
+ if(!duplicateAttributeDef){
+ String previousIDAttributeName = (String)fTableOfIDAttributeNames.get( elementName );//rule a)
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_MORE_THAN_ONE_ID_ATTRIBUTE",
+ new Object[]{ elementName, previousIDAttributeName, attributeName},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ }
+
+ //
+ // VC: One Notation Per Element Type, should check if there is a
+ // duplicate NOTATION attribute
+
+ if (type == XMLSymbols.fNOTATIONSymbol) {
+ // VC: Notation Attributes: all notation names in the
+ // (attribute) declaration must be declared.
+ for (int i=0; ipcdata() method. A children content model will
+ * contain additional groups and/or elements.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see #any
+ * @see #empty
+ */
+ public void startGroup(Augmentations augs) throws XNIException {
+
+ fMixed = false;
+ // call handlers
+ if(fDTDGrammar != null)
+ fDTDGrammar.startGroup(augs);
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.startGroup(augs);
+ }
+
+ } // startGroup()
+
+ /**
+ * The appearance of "#PCDATA" within a group signifying a
+ * mixed content model. This method will be the first called
+ * following the content model's startGroup() .
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see #startGroup
+ */
+ public void pcdata(Augmentations augs) {
+ fMixed = true;
+ if(fDTDGrammar != null)
+ fDTDGrammar.pcdata(augs);
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.pcdata(augs);
+ }
+ } // pcdata()
+
+ /**
+ * A referenced element in a mixed or children content model.
+ *
+ * @param elementName The name of the referenced element.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void element(String elementName, Augmentations augs) throws XNIException {
+
+ // check VC: No duplicate Types, in a single mixed-content declaration
+ if (fMixed && fValidation) {
+ if (fMixedElementTypes.contains(elementName)) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "DuplicateTypeInMixedContent",
+ new Object[]{fDTDElementDeclName, elementName},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ else {
+ fMixedElementTypes.add(elementName);
+ }
+ }
+
+ // call handlers
+ if(fDTDGrammar != null)
+ fDTDGrammar.element(elementName, augs);
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.element(elementName, augs);
+ }
+
+ } // childrenElement(String)
+
+ /**
+ * The separator between choices or sequences of a mixed or children
+ * content model.
+ *
+ * @param separator The type of children separator.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see #SEPARATOR_CHOICE
+ * @see #SEPARATOR_SEQUENCE
+ */
+ public void separator(short separator, Augmentations augs)
+ throws XNIException {
+
+ // call handlers
+ if(fDTDGrammar != null)
+ fDTDGrammar.separator(separator, augs);
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.separator(separator, augs);
+ }
+
+ } // separator(short)
+
+ /**
+ * The occurrence count for a child in a children content model or
+ * for the mixed content model group.
+ *
+ * @param occurrence The occurrence count for the last element
+ * or group.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ *
+ * @see #OCCURS_ZERO_OR_ONE
+ * @see #OCCURS_ZERO_OR_MORE
+ * @see #OCCURS_ONE_OR_MORE
+ */
+ public void occurrence(short occurrence, Augmentations augs)
+ throws XNIException {
+
+ // call handlers
+ if(fDTDGrammar != null)
+ fDTDGrammar.occurrence(occurrence, augs);
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.occurrence(occurrence, augs);
+ }
+
+ } // occurrence(short)
+
+ /**
+ * The end of a group for mixed or children content models.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endGroup(Augmentations augs) throws XNIException {
+
+ // call handlers
+ if(fDTDGrammar != null)
+ fDTDGrammar.endGroup(augs);
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.endGroup(augs);
+ }
+
+ } // endGroup()
+
+ /**
+ * The end of a content model.
+ *
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endContentModel(Augmentations augs) throws XNIException {
+
+ // call handlers
+ if(fDTDGrammar != null)
+ fDTDGrammar.endContentModel(augs);
+ if (fDTDContentModelHandler != null) {
+ fDTDContentModelHandler.endContentModel(augs);
+ }
+
+ } // endContentModel()
+
+ //
+ // Private methods
+ //
+
+ /**
+ * Normalize the attribute value of a non CDATA default attribute
+ * collapsing sequences of space characters (x20)
+ *
+ * @param value The value to normalize
+ * @return Whether the value was changed or not.
+ */
+ private boolean normalizeDefaultAttrValue(XMLString value) {
+
+ boolean skipSpace = true; // skip leading spaces
+ int current = value.offset;
+ int end = value.offset + value.length;
+ for (int i = value.offset; i < end; i++) {
+ if (value.ch[i] == ' ') {
+ if (!skipSpace) {
+ // take the first whitespace as a space and skip the others
+ value.ch[current++] = ' ';
+ skipSpace = true;
+ }
+ else {
+ // just skip it.
+ }
+ }
+ else {
+ // simply shift non space chars if needed
+ if (current != i) {
+ value.ch[current] = value.ch[i];
+ }
+ current++;
+ skipSpace = false;
+ }
+ }
+ if (current != end) {
+ if (skipSpace) {
+ // if we finished on a space trim it
+ current--;
+ }
+ // set the new value length
+ value.length = current - value.offset;
+ return true;
+ }
+ return false;
+ }
+
+ protected boolean isValidNmtoken(String nmtoken) {
+ return XMLChar.isValidNmtoken(nmtoken);
+ } // isValidNmtoken(String): boolean
+
+ protected boolean isValidName(String name) {
+ return XMLChar.isValidName(name);
+ } // isValidName(String): boolean
+
+ /**
+ * Checks that all elements referenced in content models have
+ * been declared. This method calls out to the error handler
+ * to indicate warnings.
+ */
+ private void checkDeclaredElements(DTDGrammar grammar) {
+ int elementIndex = grammar.getFirstElementDeclIndex();
+ XMLContentSpec contentSpec = new XMLContentSpec();
+ while (elementIndex >= 0) {
+ int type = grammar.getContentSpecType(elementIndex);
+ if (type == XMLElementDecl.TYPE_CHILDREN || type == XMLElementDecl.TYPE_MIXED) {
+ checkDeclaredElements(grammar,
+ elementIndex,
+ grammar.getContentSpecIndex(elementIndex),
+ contentSpec);
+ }
+ elementIndex = grammar.getNextElementDeclIndex(elementIndex);
+ }
+ }
+
+ /**
+ * Does a recursive (if necessary) check on the specified element's
+ * content spec to make sure that all children refer to declared
+ * elements.
+ */
+ private void checkDeclaredElements(DTDGrammar grammar, int elementIndex,
+ int contentSpecIndex, XMLContentSpec contentSpec) {
+ grammar.getContentSpec(contentSpecIndex, contentSpec);
+ if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
+ String value = (String) contentSpec.value;
+ if (value != null && grammar.getElementDeclIndex(value) == -1) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "UndeclaredElementInContentSpec",
+ new Object[]{grammar.getElementDeclName(elementIndex).rawname, value},
+ XMLErrorReporter.SEVERITY_WARNING);
+ }
+ }
+ // It's not a leaf, so we have to recurse its left and maybe right
+ // nodes. Save both values before we recurse and trash the node.
+ else if ((contentSpec.type == XMLContentSpec.CONTENTSPECNODE_CHOICE)
+ || (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_SEQ)) {
+ final int leftNode = ((int[])contentSpec.value)[0];
+ final int rightNode = ((int[])contentSpec.otherValue)[0];
+ // Recurse on both children.
+ checkDeclaredElements(grammar, elementIndex, leftNode, contentSpec);
+ checkDeclaredElements(grammar, elementIndex, rightNode, contentSpec);
+ }
+ else if (contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
+ || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE
+ || contentSpec.type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
+ final int leftNode = ((int[])contentSpec.value)[0];
+ checkDeclaredElements(grammar, elementIndex, leftNode, contentSpec);
+ }
+ }
+
+} // class XMLDTDProcessor
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDValidator.java
new file mode 100644
index 0000000..5b2de56
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDValidator.java
@@ -0,0 +1,2118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import java.util.Iterator;
+
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.impl.RevalidationHandler;
+import org.apache.xerces.impl.XMLEntityManager;
+import org.apache.xerces.impl.XMLErrorReporter;
+import org.apache.xerces.impl.dtd.models.ContentModelValidator;
+import org.apache.xerces.impl.dv.DTDDVFactory;
+import org.apache.xerces.impl.dv.DatatypeValidator;
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.impl.validation.ValidationManager;
+import org.apache.xerces.impl.validation.ValidationState;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLAttributes;
+import org.apache.xerces.xni.XMLDocumentHandler;
+import org.apache.xerces.xni.XMLLocator;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.grammars.Grammar;
+import org.apache.xerces.xni.grammars.XMLGrammarDescription;
+import org.apache.xerces.xni.grammars.XMLGrammarPool;
+import org.apache.xerces.xni.parser.XMLComponent;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLDocumentFilter;
+import org.apache.xerces.xni.parser.XMLDocumentSource;
+
+/**
+ * The DTD validator. The validator implements a document
+ * filter: receiving document events from the scanner; validating
+ * the content and structure; augmenting the InfoSet, if applicable;
+ * and notifying the parser of the information resulting from the
+ * validation process.
+ * Formerly, this component also handled DTD events and grammar construction.
+ * To facilitate the development of a meaningful DTD grammar caching/preparsing
+ * framework, this functionality has been moved into the XMLDTDLoader
+ * class. Therefore, this class no longer implements the DTDFilter
+ * or DTDContentModelFilter interfaces.
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/namespaces
+ * - http://xml.org/sax/features/validation
+ * - http://apache.org/xml/features/validation/dynamic
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/grammar-pool
+ * - http://apache.org/xml/properties/internal/datatype-validator-factory
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Eric Ye, IBM
+ * @author Andy Clark, IBM
+ * @author Jeffrey Rodriguez IBM
+ * @author Neil Graham, IBM
+ *
+ * @version $Id$
+ */
+public class XMLDTDValidator
+ implements XMLComponent, XMLDocumentFilter, XMLDTDValidatorFilter, RevalidationHandler {
+
+ //
+ // Constants
+ //
+
+ /** Symbol: "<<datatypes>>". */
+
+ /** Top level scope (-1). */
+ private static final int TOP_LEVEL_SCOPE = -1;
+
+ // feature identifiers
+
+ /** Feature identifier: namespaces. */
+ protected static final String NAMESPACES =
+ Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
+
+ /** Feature identifier: validation. */
+ protected static final String VALIDATION =
+ Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
+
+ /** Feature identifier: dynamic validation. */
+ protected static final String DYNAMIC_VALIDATION =
+ Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
+
+ /** Feature identifier: balance syntax trees. */
+ protected static final String BALANCE_SYNTAX_TREES =
+ Constants.XERCES_FEATURE_PREFIX + Constants.BALANCE_SYNTAX_TREES;
+
+ /** Feature identifier: warn on duplicate attdef */
+ protected static final String WARN_ON_DUPLICATE_ATTDEF =
+ Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
+
+ protected static final String PARSER_SETTINGS =
+ Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
+
+
+
+ // property identifiers
+
+ /** Property identifier: symbol table. */
+ protected static final String SYMBOL_TABLE =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
+
+ /** Property identifier: error reporter. */
+ protected static final String ERROR_REPORTER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
+
+ /** Property identifier: grammar pool. */
+ protected static final String GRAMMAR_POOL =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
+
+ /** Property identifier: datatype validator factory. */
+ protected static final String DATATYPE_VALIDATOR_FACTORY =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
+
+ // property identifier: ValidationManager
+ protected static final String VALIDATION_MANAGER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
+
+ // recognized features and properties
+
+ /** Recognized features. */
+ private static final String[] RECOGNIZED_FEATURES = {
+ NAMESPACES,
+ VALIDATION,
+ DYNAMIC_VALIDATION,
+ BALANCE_SYNTAX_TREES
+ };
+
+ /** Feature defaults. */
+ private static final Boolean[] FEATURE_DEFAULTS = {
+ null,
+ null,
+ Boolean.FALSE,
+ Boolean.FALSE,
+ };
+
+ /** Recognized properties. */
+ private static final String[] RECOGNIZED_PROPERTIES = {
+ SYMBOL_TABLE,
+ ERROR_REPORTER,
+ GRAMMAR_POOL,
+ DATATYPE_VALIDATOR_FACTORY,
+ VALIDATION_MANAGER
+ };
+
+ /** Property defaults. */
+ private static final Object[] PROPERTY_DEFAULTS = {
+ null,
+ null,
+ null,
+ null,
+ null,
+ };
+
+ // debugging
+
+ /** Compile to true to debug attributes. */
+ private static final boolean DEBUG_ATTRIBUTES = false;
+
+ /** Compile to true to debug element children. */
+ private static final boolean DEBUG_ELEMENT_CHILDREN = false;
+
+ //
+ // Data
+ //
+
+ // updated during reset
+ protected ValidationManager fValidationManager = null;
+
+ // validation state
+ protected final ValidationState fValidationState = new ValidationState();
+
+ // features
+
+ /** Namespaces. */
+ protected boolean fNamespaces;
+
+ /** Validation. */
+ protected boolean fValidation;
+
+ /** Validation against only DTD */
+ protected boolean fDTDValidation;
+
+ /**
+ * Dynamic validation. This state of this feature is only useful when
+ * the validation feature is set to true .
+ */
+ protected boolean fDynamicValidation;
+
+ /** Controls whether the DTD grammar produces balanced syntax trees. */
+ protected boolean fBalanceSyntaxTrees;
+
+ /** warn on duplicate attribute definition, this feature works only when validation is true */
+ protected boolean fWarnDuplicateAttdef;
+
+ // properties
+
+ /** Symbol table. */
+ protected SymbolTable fSymbolTable;
+
+ /** Error reporter. */
+ protected XMLErrorReporter fErrorReporter;
+
+ // the grammar pool
+ protected XMLGrammarPool fGrammarPool;
+
+ /** Grammar bucket. */
+ protected DTDGrammarBucket fGrammarBucket;
+
+ /* location of the document as passed in from startDocument call */
+ protected XMLLocator fDocLocation;
+
+ /** Namespace support. */
+ protected NamespaceContext fNamespaceContext = null;
+
+ /** Datatype validator factory. */
+ protected DTDDVFactory fDatatypeValidatorFactory;
+
+ // handlers
+
+ /** Document handler. */
+ protected XMLDocumentHandler fDocumentHandler;
+
+ protected XMLDocumentSource fDocumentSource;
+ // grammars
+
+ /** DTD Grammar. */
+ protected DTDGrammar fDTDGrammar;
+
+ // state
+
+ /** True if seen DOCTYPE declaration. */
+ protected boolean fSeenDoctypeDecl = false;
+
+ /** Perform validation. */
+ private boolean fPerformValidation;
+
+ /** Schema type: None, DTD, Schema */
+ private String fSchemaType;
+
+ // information regarding the current element
+
+ /** Current element name. */
+ private final QName fCurrentElement = new QName();
+
+ /** Current element index. */
+ private int fCurrentElementIndex = -1;
+
+ /** Current content spec type. */
+ private int fCurrentContentSpecType = -1;
+
+ /** The root element name. */
+ private final QName fRootElement = new QName();
+
+ private boolean fInCDATASection = false;
+ // element stack
+
+ /** Element index stack. */
+ private int[] fElementIndexStack = new int[8];
+
+ /** Content spec type stack. */
+ private int[] fContentSpecTypeStack = new int[8];
+
+ /** Element name stack. */
+ private QName[] fElementQNamePartsStack = new QName[8];
+
+ // children list and offset stack
+
+ /**
+ * Element children. This data structure is a growing stack that
+ * holds the children of elements from the root to the current
+ * element depth. This structure never gets "deeper" than the
+ * deepest element. Space is re-used once each element is closed.
+ *
+ * Note: This is much more efficient use of memory
+ * than creating new arrays for each element depth.
+ *
+ * Note: The use of this data structure is for
+ * validation "on the way out". If the validation model changes to
+ * "on the way in", then this data structure is not needed.
+ */
+ private QName[] fElementChildren = new QName[32];
+
+ /** Element children count. */
+ private int fElementChildrenLength = 0;
+
+ /**
+ * Element children offset stack. This stack refers to offsets
+ * into the fElementChildren array.
+ * @see #fElementChildren
+ */
+ private int[] fElementChildrenOffsetStack = new int[32];
+
+ /** Element depth. */
+ private int fElementDepth = -1;
+
+ // validation states
+
+ /** True if seen the root element. */
+ private boolean fSeenRootElement = false;
+
+ /** True if inside of element content. */
+ private boolean fInElementContent = false;
+
+ // temporary variables
+
+ /** Temporary element declaration. */
+ private final XMLElementDecl fTempElementDecl = new XMLElementDecl();
+
+ /** Temporary atribute declaration. */
+ private final XMLAttributeDecl fTempAttDecl = new XMLAttributeDecl();
+
+ /** Temporary entity declaration. */
+ private final XMLEntityDecl fEntityDecl = new XMLEntityDecl();
+
+ /** Temporary qualified name. */
+ private final QName fTempQName = new QName();
+
+ /** Temporary string buffers. */
+ private final StringBuffer fBuffer = new StringBuffer();
+
+ // symbols: general
+
+ // attribute validators
+
+ /** Datatype validator: ID. */
+ protected DatatypeValidator fValID;
+
+ /** Datatype validator: IDREF. */
+ protected DatatypeValidator fValIDRef;
+
+ /** Datatype validator: IDREFS. */
+ protected DatatypeValidator fValIDRefs;
+
+ /** Datatype validator: ENTITY. */
+ protected DatatypeValidator fValENTITY;
+
+ /** Datatype validator: ENTITIES. */
+ protected DatatypeValidator fValENTITIES;
+
+ /** Datatype validator: NMTOKEN. */
+ protected DatatypeValidator fValNMTOKEN;
+
+ /** Datatype validator: NMTOKENS. */
+ protected DatatypeValidator fValNMTOKENS;
+
+ /** Datatype validator: NOTATION. */
+ protected DatatypeValidator fValNOTATION;
+
+ // to check for duplicate ID or ANNOTATION attribute declare in
+ // ATTLIST, and misc VCs
+
+ //
+ // Constructors
+ //
+
+ /** Default constructor. */
+ public XMLDTDValidator() {
+
+ // initialize data
+ for (int i = 0; i < fElementQNamePartsStack.length; i++) {
+ fElementQNamePartsStack[i] = new QName();
+ }
+ fGrammarBucket = new DTDGrammarBucket();
+
+ } // ()
+
+ DTDGrammarBucket getGrammarBucket() {
+ return fGrammarBucket;
+ } // getGrammarBucket(): DTDGrammarBucket
+
+ //
+ // XMLComponent methods
+ //
+
+ /*
+ * Resets the component. The component can query the component manager
+ * about any features and properties that affect the operation of the
+ * component.
+ *
+ * @param componentManager The component manager.
+ *
+ * @throws SAXException Thrown by component on finitialization error.
+ * For example, if a feature or property is
+ * required for the operation of the component, the
+ * component manager may throw a
+ * SAXNotRecognizedException or a
+ * SAXNotSupportedException.
+ */
+ public void reset(XMLComponentManager componentManager)
+ throws XMLConfigurationException {
+
+ // clear grammars
+ fDTDGrammar = null;
+ fSeenDoctypeDecl = false;
+ fInCDATASection = false;
+ // initialize state
+ fSeenRootElement = false;
+ fInElementContent = false;
+ fCurrentElementIndex = -1;
+ fCurrentContentSpecType = -1;
+
+ fRootElement.clear();
+
+ fValidationState.resetIDTables();
+
+ fGrammarBucket.clear();
+ fElementDepth = -1;
+ fElementChildrenLength = 0;
+
+ boolean parser_settings;
+ try {
+ parser_settings = componentManager.getFeature(PARSER_SETTINGS);
+ }
+ catch (XMLConfigurationException e){
+ parser_settings = true;
+ }
+
+ if (!parser_settings){
+ // parser settings have not been changed
+ fValidationManager.addValidationState(fValidationState);
+ return;
+ }
+
+ // sax features
+ try {
+ fNamespaces = componentManager.getFeature(NAMESPACES);
+ }
+ catch (XMLConfigurationException e) {
+ fNamespaces = true;
+ }
+ try {
+ fValidation = componentManager.getFeature(VALIDATION);
+ }
+ catch (XMLConfigurationException e) {
+ fValidation = false;
+ }
+ try {
+ fDTDValidation = !(componentManager.getFeature(Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE));
+ }
+ catch (XMLConfigurationException e) {
+ // must be in a schema-less configuration!
+ fDTDValidation = true;
+ }
+
+ // Xerces features
+ try {
+ fDynamicValidation = componentManager.getFeature(DYNAMIC_VALIDATION);
+ }
+ catch (XMLConfigurationException e) {
+ fDynamicValidation = false;
+ }
+
+ try {
+ fBalanceSyntaxTrees = componentManager.getFeature(BALANCE_SYNTAX_TREES);
+ }
+ catch (XMLConfigurationException e) {
+ fBalanceSyntaxTrees = false;
+ }
+
+ try {
+ fWarnDuplicateAttdef = componentManager.getFeature(WARN_ON_DUPLICATE_ATTDEF);
+ }
+ catch (XMLConfigurationException e) {
+ fWarnDuplicateAttdef = false;
+ }
+
+ try {
+ fSchemaType = (String)componentManager.getProperty (Constants.JAXP_PROPERTY_PREFIX
+ + Constants.SCHEMA_LANGUAGE);
+ }
+ catch (XMLConfigurationException e){
+ fSchemaType = null;
+ }
+
+ fValidationManager= (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
+ fValidationManager.addValidationState(fValidationState);
+ fValidationState.setUsingNamespaces(fNamespaces);
+
+ // get needed components
+ fErrorReporter = (XMLErrorReporter)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.ERROR_REPORTER_PROPERTY);
+ fSymbolTable = (SymbolTable)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.SYMBOL_TABLE_PROPERTY);
+ try {
+ fGrammarPool= (XMLGrammarPool)componentManager.getProperty(GRAMMAR_POOL);
+ } catch (XMLConfigurationException e) {
+ fGrammarPool = null;
+ }
+
+ fDatatypeValidatorFactory = (DTDDVFactory)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY);
+ init();
+
+ } // reset(XMLComponentManager)
+
+ /**
+ * Returns a list of feature identifiers that are recognized by
+ * this component. This method may return null if no features
+ * are recognized by this component.
+ */
+ public String[] getRecognizedFeatures() {
+ return (String[])(RECOGNIZED_FEATURES.clone());
+ } // getRecognizedFeatures():String[]
+
+ /**
+ * Sets the state of a feature. This method is called by the component
+ * manager any time after reset when a feature changes state.
+ *
+ * Note: Components should silently ignore features
+ * that do not affect the operation of the component.
+ *
+ * @param featureId The feature identifier.
+ * @param state The state of the feature.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setFeature(String featureId, boolean state)
+ throws XMLConfigurationException {
+ } // setFeature(String,boolean)
+
+ /**
+ * Returns a list of property identifiers that are recognized by
+ * this component. This method may return null if no properties
+ * are recognized by this component.
+ */
+ public String[] getRecognizedProperties() {
+ return (String[])(RECOGNIZED_PROPERTIES.clone());
+ } // getRecognizedProperties():String[]
+
+ /**
+ * Sets the value of a property. This method is called by the component
+ * manager any time after reset when a property changes value.
+ *
+ * Note: Components should silently ignore properties
+ * that do not affect the operation of the component.
+ *
+ * @param propertyId The property identifier.
+ * @param value The value of the property.
+ *
+ * @throws SAXNotRecognizedException The component should not throw
+ * this exception.
+ * @throws SAXNotSupportedException The component should not throw
+ * this exception.
+ */
+ public void setProperty(String propertyId, Object value)
+ throws XMLConfigurationException {
+ } // setProperty(String,Object)
+
+ /**
+ * Returns the default state for a feature, or null if this
+ * component does not want to report a default value for this
+ * feature.
+ *
+ * @param featureId The feature identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Boolean getFeatureDefault(String featureId) {
+ for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
+ if (RECOGNIZED_FEATURES[i].equals(featureId)) {
+ return FEATURE_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getFeatureDefault(String):Boolean
+
+ /**
+ * Returns the default state for a property, or null if this
+ * component does not want to report a default value for this
+ * property.
+ *
+ * @param propertyId The property identifier.
+ *
+ * @since Xerces 2.2.0
+ */
+ public Object getPropertyDefault(String propertyId) {
+ for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
+ if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
+ return PROPERTY_DEFAULTS[i];
+ }
+ }
+ return null;
+ } // getPropertyDefault(String):Object
+
+ //
+ // XMLDocumentSource methods
+ //
+
+ /** Sets the document handler to receive information about the document. */
+ public void setDocumentHandler(XMLDocumentHandler documentHandler) {
+ fDocumentHandler = documentHandler;
+ } // setDocumentHandler(XMLDocumentHandler)
+
+ /** Returns the document handler */
+ public XMLDocumentHandler getDocumentHandler() {
+ return fDocumentHandler;
+ } // getDocumentHandler(): XMLDocumentHandler
+
+
+ //
+ // XMLDocumentHandler methods
+ //
+
+ /** Sets the document source */
+ public void setDocumentSource(XMLDocumentSource source){
+ fDocumentSource = source;
+ } // setDocumentSource
+
+ /** Returns the document source */
+ public XMLDocumentSource getDocumentSource (){
+ return fDocumentSource;
+ } // getDocumentSource
+
+ /**
+ * The start of the document.
+ *
+ * @param locator The system identifier of the entity if the entity
+ * is external, null otherwise.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal entities or a document entity that is
+ * parsed from a java.io.Reader).
+ * @param namespaceContext
+ * The namespace context in effect at the
+ * start of this document.
+ * This object represents the current context.
+ * Implementors of this class are responsible
+ * for copying the namespace bindings from the
+ * the current context (and its parent contexts)
+ * if that information is important.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startDocument(XMLLocator locator, String encoding,
+ NamespaceContext namespaceContext, Augmentations augs)
+ throws XNIException {
+
+ // call handlers
+ // get initial grammars
+ if (fGrammarPool != null) {
+ Grammar [] grammars = fGrammarPool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_DTD);
+ final int length = (grammars != null) ? grammars.length : 0;
+ for (int i = 0; i < length; ++i) {
+ fGrammarBucket.putGrammar((DTDGrammar)grammars[i]);
+ }
+ }
+ fDocLocation = locator;
+ fNamespaceContext = namespaceContext;
+
+ if (fDocumentHandler != null) {
+ fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
+ }
+
+ } // startDocument(XMLLocator,String)
+
+ /**
+ * Notifies of the presence of an XMLDecl line in the document. If
+ * present, this method will be called immediately following the
+ * startDocument call.
+ *
+ * @param version The XML version.
+ * @param encoding The IANA encoding name of the document, or null if
+ * not specified.
+ * @param standalone The standalone value, or null if not specified.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void xmlDecl(String version, String encoding, String standalone, Augmentations augs)
+ throws XNIException {
+
+ // save standalone state
+ fGrammarBucket.setStandalone(standalone != null && standalone.equals("yes"));
+
+ // call handlers
+ if (fDocumentHandler != null) {
+ fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
+ }
+
+ } // xmlDecl(String,String,String)
+
+ /**
+ * Notifies of the presence of the DOCTYPE line in the document.
+ *
+ * @param rootElement The name of the root element.
+ * @param publicId The public identifier if an external DTD or null
+ * if the external DTD is specified using SYSTEM.
+ * @param systemId The system identifier if an external DTD, null
+ * otherwise.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void doctypeDecl(String rootElement, String publicId, String systemId,
+ Augmentations augs)
+ throws XNIException {
+
+ // save root element state
+ fSeenDoctypeDecl = true;
+ fRootElement.setValues(null, rootElement, rootElement, null);
+ // find or create grammar:
+ String eid = null;
+ try {
+ eid = XMLEntityManager.expandSystemId(systemId, fDocLocation.getExpandedSystemId(), false);
+ } catch (java.io.IOException e) {
+ }
+ XMLDTDDescription grammarDesc = new XMLDTDDescription(publicId, systemId, fDocLocation.getExpandedSystemId(), eid, rootElement);
+ fDTDGrammar = fGrammarBucket.getGrammar(grammarDesc);
+ if(fDTDGrammar == null) {
+ // give grammar pool a chance...
+ //
+ // Do not bother checking the pool if no public or system identifier was provided.
+ // Since so many different DTDs have roots in common, using only a root name as the
+ // key may cause an unexpected grammar to be retrieved from the grammar pool. This scenario
+ // would occur when an ExternalSubsetResolver has been queried and the
+ // XMLInputSource returned contains an input stream but no external identifier.
+ // This can never happen when the instance document specified a DOCTYPE. -- mrglavas
+ if (fGrammarPool != null && (systemId != null || publicId != null)) {
+ fDTDGrammar = (DTDGrammar)fGrammarPool.retrieveGrammar(grammarDesc);
+ }
+ }
+ if(fDTDGrammar == null) {
+ // we'll have to create it...
+ if (!fBalanceSyntaxTrees) {
+ fDTDGrammar = new DTDGrammar(fSymbolTable, grammarDesc);
+ }
+ else {
+ fDTDGrammar = new BalancedDTDGrammar(fSymbolTable, grammarDesc);
+ }
+ } else {
+ // we've found a cached one;so let's make sure not to read
+ // any external subset!
+ fValidationManager.setCachedDTD(true);
+ }
+ fGrammarBucket.setActiveGrammar(fDTDGrammar);
+
+ // call handlers
+ if (fDocumentHandler != null) {
+ fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
+ }
+
+ } // doctypeDecl(String,String,String, Augmentations)
+
+
+ /**
+ * The start of an element.
+ *
+ * @param element The name of the element.
+ * @param attributes The element attributes.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
+ throws XNIException {
+
+ handleStartElement(element, attributes, augs);
+ // call handlers
+ if (fDocumentHandler != null) {
+ fDocumentHandler.startElement(element, attributes, augs);
+
+ }
+
+ } // startElement(QName,XMLAttributes)
+
+ /**
+ * An empty element.
+ *
+ * @param element The name of the element.
+ * @param attributes The element attributes.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
+ throws XNIException {
+
+ boolean removed = handleStartElement(element, attributes, augs);
+
+ if (fDocumentHandler !=null) {
+ fDocumentHandler.emptyElement(element, attributes, augs);
+ }
+ if (!removed) {
+ handleEndElement(element, augs, true);
+ }
+
+
+ } // emptyElement(QName,XMLAttributes)
+
+ /**
+ * Character content.
+ *
+ * @param text The content.
+ *
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void characters(XMLString text, Augmentations augs) throws XNIException {
+
+ boolean callNextCharacters = true;
+
+ // REVISIT: [Q] Is there a more efficient way of doing this?
+ // Perhaps if the scanner told us so we don't have to
+ // look at the characters again. -Ac
+ boolean allWhiteSpace = true;
+ for (int i=text.offset; i< text.offset+text.length; i++) {
+ if (!isSpace(text.ch[i])) {
+ allWhiteSpace = false;
+ break;
+ }
+ }
+ // call the ignoreableWhiteSpace callback
+ // never call ignorableWhitespace if we are in cdata section
+ if (fInElementContent && allWhiteSpace && !fInCDATASection) {
+ if (fDocumentHandler != null) {
+ fDocumentHandler.ignorableWhitespace(text, augs);
+ callNextCharacters = false;
+ }
+ }
+
+ // validate
+ if (fPerformValidation) {
+ if (fInElementContent) {
+ if (fGrammarBucket.getStandalone() &&
+ fDTDGrammar.getElementDeclIsExternal(fCurrentElementIndex)) {
+ if (allWhiteSpace) {
+ fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
+ "MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE",
+ null, XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ if (!allWhiteSpace) {
+ charDataInContent();
+ }
+
+ // For E15.2
+ if (augs != null && augs.getItem(Constants.CHAR_REF_PROBABLE_WS) == Boolean.TRUE) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_CONTENT_INVALID_SPECIFIED",
+ new Object[]{ fCurrentElement.rawname,
+ fDTDGrammar.getContentSpecAsString(fElementDepth),
+ "character reference"},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+
+ if (fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
+ charDataInContent();
+ }
+ }
+
+ // call handlers
+ if (callNextCharacters && fDocumentHandler != null) {
+ fDocumentHandler.characters(text, augs);
+ }
+
+ } // characters(XMLString)
+
+
+
+ /**
+ * Ignorable whitespace. For this method to be called, the document
+ * source must have some way of determining that the text containing
+ * only whitespace characters should be considered ignorable. For
+ * example, the validator can determine if a length of whitespace
+ * characters in the document are ignorable based on the element
+ * content model.
+ *
+ * @param text The ignorable whitespace.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
+
+ // call handlers
+ if (fDocumentHandler != null) {
+ fDocumentHandler.ignorableWhitespace(text, augs);
+ }
+
+ } // ignorableWhitespace(XMLString)
+
+ /**
+ * The end of an element.
+ *
+ * @param element The name of the element.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endElement(QName element, Augmentations augs) throws XNIException {
+
+ handleEndElement(element, augs, false);
+
+ } // endElement(QName)
+
+ /**
+ * The start of a CDATA section.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void startCDATA(Augmentations augs) throws XNIException {
+
+ if (fPerformValidation && fInElementContent) {
+ charDataInContent();
+ }
+ fInCDATASection = true;
+ // call handlers
+ if (fDocumentHandler != null) {
+ fDocumentHandler.startCDATA(augs);
+ }
+
+ } // startCDATA()
+
+ /**
+ * The end of a CDATA section.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endCDATA(Augmentations augs) throws XNIException {
+
+ fInCDATASection = false;
+ // call handlers
+ if (fDocumentHandler != null) {
+ fDocumentHandler.endCDATA(augs);
+ }
+
+ } // endCDATA()
+
+ /**
+ * The end of the document.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void endDocument(Augmentations augs) throws XNIException {
+
+ // call handlers
+ if (fDocumentHandler != null) {
+ fDocumentHandler.endDocument(augs);
+ }
+
+ } // endDocument()
+
+ /**
+ * A comment.
+ *
+ * @param text The text in the comment.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by application to signal an error.
+ */
+ public void comment(XMLString text, Augmentations augs) throws XNIException {
+ // fixes E15.1
+ if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
+ fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
+ if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_CONTENT_INVALID_SPECIFIED",
+ new Object[]{ fCurrentElement.rawname,
+ "EMPTY",
+ "comment"},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ // call handlers
+ if (fDocumentHandler != null) {
+ fDocumentHandler.comment(text, augs);
+ }
+
+ } // comment(XMLString)
+
+
+ /**
+ * A processing instruction. Processing instructions consist of a
+ * target name and, optionally, text data. The data is only meaningful
+ * to the application.
+ *
+ * Typically, a processing instruction's data will contain a series
+ * of pseudo-attributes. These pseudo-attributes follow the form of
+ * element attributes but are not parsed or presented
+ * to the application as anything other than text. The application is
+ * responsible for parsing the data.
+ *
+ * @param target The target.
+ * @param data The data or null if none specified.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void processingInstruction(String target, XMLString data, Augmentations augs)
+ throws XNIException {
+
+ // fixes E15.1
+ if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
+ fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
+ if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_CONTENT_INVALID_SPECIFIED",
+ new Object[]{ fCurrentElement.rawname,
+ "EMPTY",
+ "processing instruction"},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ // call handlers
+ if (fDocumentHandler != null) {
+ fDocumentHandler.processingInstruction(target, data, augs);
+ }
+ } // processingInstruction(String,XMLString)
+
+ /**
+ * This method notifies the start of a general entity.
+ *
+ * Note: This method is not called for entity references
+ * appearing as part of attribute values.
+ *
+ * @param name The name of the general entity.
+ * @param identifier The resource identifier.
+ * @param encoding The auto-detected IANA encoding name of the entity
+ * stream. This value will be null in those situations
+ * where the entity encoding is not auto-detected (e.g.
+ * internal entities or a document entity that is
+ * parsed from a java.io.Reader).
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException Thrown by handler to signal an error.
+ */
+ public void startGeneralEntity(String name,
+ XMLResourceIdentifier identifier,
+ String encoding,
+ Augmentations augs) throws XNIException {
+ if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
+ fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
+ // fixes E15.1
+ if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_CONTENT_INVALID_SPECIFIED",
+ new Object[]{ fCurrentElement.rawname,
+ "EMPTY", "ENTITY"},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ if (fGrammarBucket.getStandalone()) {
+ XMLDTDLoader.checkStandaloneEntityRef(name, fDTDGrammar, fEntityDecl, fErrorReporter);
+ }
+ }
+ if (fDocumentHandler != null) {
+ fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
+ }
+ }
+
+ /**
+ * This method notifies the end of a general entity.
+ *
+ * Note: This method is not called for entity references
+ * appearing as part of attribute values.
+ *
+ * @param name The name of the entity.
+ * @param augs Additional information that may include infoset augmentations
+ *
+ * @exception XNIException
+ * Thrown by handler to signal an error.
+ */
+ public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
+ // call handlers
+ if (fDocumentHandler != null) {
+ fDocumentHandler.endGeneralEntity(name, augs);
+ }
+ } // endEntity(String)
+
+ /**
+ * Notifies of the presence of a TextDecl line in an entity. If present,
+ * this method will be called immediately following the startParameterEntity call.
+ *
+ * Note: This method is only called for external
+ * parameter entities referenced in the DTD.
+ *
+ * @param version The XML version, or null if not specified.
+ * @param encoding The IANA encoding name of the entity.
+ * @param augs Additional information that may include infoset
+ * augmentations.
+ *
+ * @throws XNIException Thrown by handler to signal an error.
+ */
+ public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
+
+ // call handlers
+ if (fDocumentHandler != null) {
+ fDocumentHandler.textDecl(version, encoding, augs);
+ }
+ }
+
+
+ public final boolean hasGrammar(){
+
+ return (fDTDGrammar != null);
+ }
+
+ public final boolean validate(){
+ // Do validation if all of the following are true:
+ // 1. The JAXP Schema Language property is not XML Schema
+ // REVISIT: since only DTD and Schema are supported at this time,
+ // such checking is sufficient. but if more schema types
+ // are introduced in the future, we'll need to change it
+ // to something like
+ // (fSchemaType == null || fSchemaType == NS_XML_DTD)
+ // 2. One of the following is true (validation features)
+ // 2.1 Dynamic validation is off, and validation is on
+ // 2.2 Dynamic validation is on, and DOCTYPE was seen
+ // 3 Xerces schema validation feature is off, or DOCTYPE was seen.
+ return (fSchemaType != Constants.NS_XMLSCHEMA) &&
+ (!fDynamicValidation && fValidation ||
+ fDynamicValidation && fSeenDoctypeDecl) &&
+ (fDTDValidation || fSeenDoctypeDecl);
+ }
+
+ //REVISIT:we can convert into functions.. adding default attribute values.. and one validating.
+
+ /** Add default attributes and validate. */
+ protected void addDTDDefaultAttrsAndValidate(QName elementName, int elementIndex,
+ XMLAttributes attributes)
+ throws XNIException {
+
+ // is there anything to do?
+ if (elementIndex == -1 || fDTDGrammar == null) {
+ return;
+ }
+
+ //
+ // Check after all specified attrs are scanned
+ // (1) report error for REQUIRED attrs that are missing (V_TAGc)
+ // (2) add default attrs (FIXED and NOT_FIXED)
+ //
+ int attlistIndex = fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);
+
+ while (attlistIndex != -1) {
+
+ fDTDGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);
+
+ if (DEBUG_ATTRIBUTES) {
+ if (fTempAttDecl != null) {
+ XMLElementDecl elementDecl = new XMLElementDecl();
+ fDTDGrammar.getElementDecl(elementIndex, elementDecl);
+ System.out.println("element: "+(elementDecl.name.localpart));
+ System.out.println("attlistIndex " + attlistIndex + "\n"+
+ "attName : '"+(fTempAttDecl.name.localpart) + "'\n"
+ + "attType : "+fTempAttDecl.simpleType.type + "\n"
+ + "attDefaultType : "+fTempAttDecl.simpleType.defaultType + "\n"
+ + "attDefaultValue : '"+fTempAttDecl.simpleType.defaultValue + "'\n"
+ + attributes.getLength() +"\n"
+ );
+ }
+ }
+ String attPrefix = fTempAttDecl.name.prefix;
+ String attLocalpart = fTempAttDecl.name.localpart;
+ String attRawName = fTempAttDecl.name.rawname;
+ String attType = getAttributeTypeName(fTempAttDecl);
+ int attDefaultType =fTempAttDecl.simpleType.defaultType;
+ String attValue = null;
+
+ if (fTempAttDecl.simpleType.defaultValue != null) {
+ attValue = fTempAttDecl.simpleType.defaultValue;
+ }
+
+ boolean specified = false;
+ boolean required = attDefaultType == XMLSimpleType.DEFAULT_TYPE_REQUIRED;
+ boolean cdata = attType == XMLSymbols.fCDATASymbol;
+
+ if (!cdata || required || attValue != null) {
+ int attrCount = attributes.getLength();
+ for (int i = 0; i < attrCount; i++) {
+ if (attributes.getQName(i) == attRawName) {
+ specified = true;
+ break;
+ }
+ }
+ }
+
+ if (!specified) {
+ if (required) {
+ if (fPerformValidation) {
+ Object[] args = {elementName.localpart, attRawName};
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED", args,
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ else if (attValue != null) {
+ if (fPerformValidation && fGrammarBucket.getStandalone()) {
+ if (fDTDGrammar.getAttributeDeclIsExternal(attlistIndex)) {
+
+ Object[] args = { elementName.localpart, attRawName};
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED", args,
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+
+ // add namespace information
+ if (fNamespaces) {
+ int index = attRawName.indexOf(':');
+ if (index != -1) {
+ attPrefix = attRawName.substring(0, index);
+ attPrefix = fSymbolTable.addSymbol(attPrefix);
+ attLocalpart = attRawName.substring(index + 1);
+ attLocalpart = fSymbolTable.addSymbol(attLocalpart);
+ }
+ }
+
+ // add attribute
+ fTempQName.setValues(attPrefix, attLocalpart, attRawName, fTempAttDecl.name.uri);
+ int newAttr = attributes.addAttribute(fTempQName, attType, attValue);
+ }
+ }
+ // get next att decl in the Grammar for this element
+ attlistIndex = fDTDGrammar.getNextAttributeDeclIndex(attlistIndex);
+ }
+
+ // now iterate through the expanded attributes for
+ // 1. if every attribute seen is declared in the DTD
+ // 2. check if the VC: default_fixed holds
+ // 3. validate every attribute.
+ int attrCount = attributes.getLength();
+ for (int i = 0; i < attrCount; i++) {
+ String attrRawName = attributes.getQName(i);
+ boolean declared = false;
+ if (fPerformValidation) {
+ if (fGrammarBucket.getStandalone()) {
+ // check VC: Standalone Document Declaration, entities
+ // references appear in the document.
+ // REVISIT: this can be combined to a single check in
+ // startEntity if we add one more argument in
+ // startEnity, inAttrValue
+ String nonNormalizedValue = attributes.getNonNormalizedValue(i);
+ if (nonNormalizedValue != null) {
+ String entityName = getExternalEntityRefInAttrValue(nonNormalizedValue);
+ if (entityName != null) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
+ new Object[]{entityName},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ }
+ }
+ int attDefIndex = -1;
+ int position =
+ fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);
+ while (position != -1) {
+ fDTDGrammar.getAttributeDecl(position, fTempAttDecl);
+ if (fTempAttDecl.name.rawname == attrRawName) {
+ // found the match att decl,
+ attDefIndex = position;
+ declared = true;
+ break;
+ }
+ position = fDTDGrammar.getNextAttributeDeclIndex(position);
+ }
+ if (!declared) {
+ if (fPerformValidation) {
+ // REVISIT - cache the elem/attr tuple so that we only
+ // give this error once for each unique occurrence
+ Object[] args = { elementName.rawname, attrRawName};
+
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_ATTRIBUTE_NOT_DECLARED",
+ args,XMLErrorReporter.SEVERITY_ERROR);
+ }
+ continue;
+ }
+ // attribute is declared
+
+ // fTempAttDecl should have the right value set now, so
+ // the following is not needed
+ // fGrammar.getAttributeDecl(attDefIndex,fTempAttDecl);
+
+ String type = getAttributeTypeName(fTempAttDecl);
+ attributes.setType(i, type);
+ attributes.getAugmentations(i).putItem(Constants.ATTRIBUTE_DECLARED, Boolean.TRUE);
+
+ boolean changedByNormalization = false;
+ String oldValue = attributes.getValue(i);
+ String attrValue = oldValue;
+ if (attributes.isSpecified(i) && type != XMLSymbols.fCDATASymbol) {
+ changedByNormalization = normalizeAttrValue(attributes, i);
+ attrValue = attributes.getValue(i);
+ if (fPerformValidation && fGrammarBucket.getStandalone()
+ && changedByNormalization
+ && fDTDGrammar.getAttributeDeclIsExternal(position)
+ ) {
+ // check VC: Standalone Document Declaration
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE",
+ new Object[]{attrRawName, oldValue, attrValue},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ if (!fPerformValidation) {
+ continue;
+ }
+ if (fTempAttDecl.simpleType.defaultType ==
+ XMLSimpleType.DEFAULT_TYPE_FIXED) {
+ String defaultValue = fTempAttDecl.simpleType.defaultValue;
+
+ if (!attrValue.equals(defaultValue)) {
+ Object[] args = {elementName.localpart,
+ attrRawName,
+ attrValue,
+ defaultValue};
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_FIXED_ATTVALUE_INVALID",
+ args, XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+
+ if (fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ENTITY ||
+ fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ENUMERATION ||
+ fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ID ||
+ fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_IDREF ||
+ fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_NMTOKEN ||
+ fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_NOTATION
+ ) {
+ validateDTDattribute(elementName, attrValue, fTempAttDecl);
+ }
+ } // for all attributes
+
+ } // addDTDDefaultAttrsAndValidate(int,XMLAttrList)
+
+ /** Checks entities in attribute values for standalone VC. */
+ protected String getExternalEntityRefInAttrValue(String nonNormalizedValue) {
+ int valLength = nonNormalizedValue.length();
+ int ampIndex = nonNormalizedValue.indexOf('&');
+ while (ampIndex != -1) {
+ if (ampIndex + 1 < valLength &&
+ nonNormalizedValue.charAt(ampIndex+1) != '#') {
+ int semicolonIndex = nonNormalizedValue.indexOf(';', ampIndex+1);
+ String entityName = nonNormalizedValue.substring(ampIndex+1, semicolonIndex);
+ entityName = fSymbolTable.addSymbol(entityName);
+ int entIndex = fDTDGrammar.getEntityDeclIndex(entityName);
+ if (entIndex > -1) {
+ fDTDGrammar.getEntityDecl(entIndex, fEntityDecl);
+ if (fEntityDecl.inExternal ||
+ (entityName = getExternalEntityRefInAttrValue(fEntityDecl.value)) != null) {
+ return entityName;
+ }
+ }
+ }
+ ampIndex = nonNormalizedValue.indexOf('&', ampIndex+1);
+ }
+ return null;
+ } // isExternalEntityRefInAttrValue(String):String
+
+ /**
+ * Validate attributes in DTD fashion.
+ */
+ protected void validateDTDattribute(QName element, String attValue,
+ XMLAttributeDecl attributeDecl)
+ throws XNIException {
+
+ switch (attributeDecl.simpleType.type) {
+ case XMLSimpleType.TYPE_ENTITY: {
+ // NOTE: Save this information because invalidStandaloneAttDef
+ boolean isAlistAttribute = attributeDecl.simpleType.list;
+
+ try {
+ if (isAlistAttribute) {
+ fValENTITIES.validate(attValue, fValidationState);
+ }
+ else {
+ fValENTITY.validate(attValue, fValidationState);
+ }
+ }
+ catch (InvalidDatatypeValueException ex) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ ex.getKey(),
+ ex.getArgs(),
+ XMLErrorReporter.SEVERITY_ERROR );
+
+ }
+ break;
+ }
+
+ case XMLSimpleType.TYPE_NOTATION:
+ case XMLSimpleType.TYPE_ENUMERATION: {
+ boolean found = false;
+ String [] enumVals = attributeDecl.simpleType.enumeration;
+ if (enumVals == null) {
+ found = false;
+ }
+ else
+ for (int i = 0; i < enumVals.length; i++) {
+ if (attValue == enumVals[i] || attValue.equals(enumVals[i])) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ StringBuffer enumValueString = new StringBuffer();
+ if (enumVals != null)
+ for (int i = 0; i < enumVals.length; i++) {
+ enumValueString.append(enumVals[i]+" ");
+ }
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_ATTRIBUTE_VALUE_NOT_IN_LIST",
+ new Object[]{attributeDecl.name.rawname, attValue, enumValueString},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ break;
+ }
+
+ case XMLSimpleType.TYPE_ID: {
+ try {
+ fValID.validate(attValue, fValidationState);
+ }
+ catch (InvalidDatatypeValueException ex) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ ex.getKey(),
+ ex.getArgs(),
+ XMLErrorReporter.SEVERITY_ERROR );
+ }
+ break;
+ }
+
+ case XMLSimpleType.TYPE_IDREF: {
+ boolean isAlistAttribute = attributeDecl.simpleType.list;//Caveat - Save this information because invalidStandaloneAttDef
+
+ try {
+ if (isAlistAttribute) {
+ fValIDRefs.validate(attValue, fValidationState);
+ }
+ else {
+ fValIDRef.validate(attValue, fValidationState);
+ }
+ }
+ catch (InvalidDatatypeValueException ex) {
+ if (isAlistAttribute) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "IDREFSInvalid",
+ new Object[]{attValue},
+ XMLErrorReporter.SEVERITY_ERROR );
+ }
+ else {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ ex.getKey(),
+ ex.getArgs(),
+ XMLErrorReporter.SEVERITY_ERROR );
+ }
+
+ }
+ break;
+ }
+
+ case XMLSimpleType.TYPE_NMTOKEN: {
+ boolean isAlistAttribute = attributeDecl.simpleType.list;//Caveat - Save this information because invalidStandaloneAttDef
+ //changes fTempAttDef
+ try {
+ if (isAlistAttribute) {
+ fValNMTOKENS.validate(attValue, fValidationState);
+ }
+ else {
+ fValNMTOKEN.validate(attValue, fValidationState);
+ }
+ }
+ catch (InvalidDatatypeValueException ex) {
+ if (isAlistAttribute) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "NMTOKENSInvalid",
+ new Object[] { attValue},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ else {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "NMTOKENInvalid",
+ new Object[] { attValue},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ break;
+ }
+
+ } // switch
+
+ } // validateDTDattribute(QName,String,XMLAttributeDecl)
+
+
+ /** Returns true if invalid standalone attribute definition. */
+ protected boolean invalidStandaloneAttDef(QName element, QName attribute) {
+ // REVISIT: This obviously needs to be fixed! -Ac
+ boolean state = true;
+ /*
+ if (fStandaloneReader == -1) {
+ return false;
+ }
+ // we are normalizing a default att value... this ok?
+ if (element.rawname == -1) {
+ return false;
+ }
+ return getAttDefIsExternal(element, attribute);
+ */
+ return state;
+ }
+
+
+ //
+ // Private methods
+ //
+
+
+ /**
+ * Normalize the attribute value of a non CDATA attributes collapsing
+ * sequences of space characters (x20)
+ *
+ * @param attributes The list of attributes
+ * @param index The index of the attribute to normalize
+ */
+ private boolean normalizeAttrValue(XMLAttributes attributes, int index) {
+ // vars
+ boolean leadingSpace = true;
+ boolean spaceStart = false;
+ boolean readingNonSpace = false;
+ int count = 0;
+ int eaten = 0;
+ String attrValue = attributes.getValue(index);
+ char[] attValue = new char[attrValue.length()];
+
+ fBuffer.setLength(0);
+ attrValue.getChars(0, attrValue.length(), attValue, 0);
+ for (int i = 0; i < attValue.length; i++) {
+
+ if (attValue[i] == ' ') {
+
+ // now the tricky part
+ if (readingNonSpace) {
+ spaceStart = true;
+ readingNonSpace = false;
+ }
+
+ if (spaceStart && !leadingSpace) {
+ spaceStart = false;
+ fBuffer.append(attValue[i]);
+ count++;
+ }
+ else {
+ if (leadingSpace || !spaceStart) {
+ eaten ++;
+ /*** BUG #3512 ***
+ int entityCount = attributes.getEntityCount(index);
+ for (int j = 0; j < entityCount; j++) {
+ int offset = attributes.getEntityOffset(index, j);
+ int length = attributes.getEntityLength(index, j);
+ if (offset <= i-eaten+1) {
+ if (offset+length >= i-eaten+1) {
+ if (length > 0)
+ length--;
+ }
+ }
+ else {
+ if (offset > 0)
+ offset--;
+ }
+ attributes.setEntityOffset(index, j, offset);
+ attributes.setEntityLength(index, j, length);
+ }
+ /***/
+ }
+ }
+
+ }
+ else {
+ readingNonSpace = true;
+ spaceStart = false;
+ leadingSpace = false;
+ fBuffer.append(attValue[i]);
+ count++;
+ }
+ }
+
+ // check if the last appended character is a space.
+ if (count > 0 && fBuffer.charAt(count-1) == ' ') {
+ fBuffer.setLength(count-1);
+ /*** BUG #3512 ***
+ int entityCount = attributes.getEntityCount(index);
+ for (int j=0; j < entityCount; j++) {
+ int offset = attributes.getEntityOffset(index, j);
+ int length = attributes.getEntityLength(index, j);
+ if (offset < count-1) {
+ if (offset+length == count) {
+ length--;
+ }
+ }
+ else {
+ offset--;
+ }
+ attributes.setEntityOffset(index, j, offset);
+ attributes.setEntityLength(index, j, length);
+ }
+ /***/
+ }
+ String newValue = fBuffer.toString();
+ attributes.setValue(index, newValue);
+ return ! attrValue.equals(newValue);
+ }
+
+ /** Root element specified. */
+ private final void rootElementSpecified(QName rootElement) throws XNIException {
+ if (fPerformValidation) {
+ String root1 = fRootElement.rawname;
+ String root2 = rootElement.rawname;
+ if (root1 == null || !root1.equals(root2)) {
+ fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
+ "RootElementTypeMustMatchDoctypedecl",
+ new Object[]{root1, root2},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ } // rootElementSpecified(QName)
+
+ /**
+ * Check that the content of an element is valid.
+ *
+ * This is the method of primary concern to the validator. This method is called
+ * upon the scanner reaching the end tag of an element. At that time, the
+ * element's children must be structurally validated, so it calls this method.
+ * The index of the element being checked (in the decl pool), is provided as
+ * well as an array of element name indexes of the children. The validator must
+ * confirm that this element can have these children in this order.
+ *
+ * This can also be called to do 'what if' testing of content models just to see
+ * if they would be valid.
+ *
+ * Note that the element index is an index into the element decl pool, whereas
+ * the children indexes are name indexes, i.e. into the string pool.
+ *
+ * A value of -1 in the children array indicates a PCDATA node. All other
+ * indexes will be positive and represent child elements. The count can be
+ * zero, since some elements have the EMPTY content model and that must be
+ * confirmed.
+ *
+ * @param elementIndex The index within the ElementDeclPool of this
+ * element.
+ * @param childCount The number of entries in the children array.
+ * @param children The children of this element.
+ *
+ * @return The value -1 if fully valid, else the 0 based index of the child
+ * that first failed. If the value returned is equal to the number
+ * of children, then additional content is required to reach a valid
+ * ending state.
+ *
+ * @exception Exception Thrown on error.
+ */
+ private int checkContent(int elementIndex,
+ QName[] children,
+ int childOffset,
+ int childCount) throws XNIException {
+
+ fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
+
+ // Get the element name index from the element
+ final String elementType = fCurrentElement.rawname;
+
+ // Get out the content spec for this element
+ final int contentType = fCurrentContentSpecType;
+
+
+ //
+ // Deal with the possible types of content. We try to optimized here
+ // by dealing specially with content models that don't require the
+ // full DFA treatment.
+ //
+ if (contentType == XMLElementDecl.TYPE_EMPTY) {
+ //
+ // If the child count is greater than zero, then this is
+ // an error right off the bat at index 0.
+ //
+ if (childCount != 0) {
+ return 0;
+ }
+ }
+ else if (contentType == XMLElementDecl.TYPE_ANY) {
+ //
+ // This one is open game so we don't pass any judgement on it
+ // at all. Its assumed to fine since it can hold anything.
+ //
+ }
+ else if (contentType == XMLElementDecl.TYPE_MIXED ||
+ contentType == XMLElementDecl.TYPE_CHILDREN) {
+ // Get the content model for this element, faulting it in if needed
+ ContentModelValidator cmElem = null;
+ cmElem = fTempElementDecl.contentModelValidator;
+ int result = cmElem.validate(children, childOffset, childCount);
+ return result;
+ }
+ else if (contentType == -1) {
+ //REVISIT
+ /****
+ reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
+ XMLMessages.VC_ELEMENT_VALID,
+ elementType);
+ /****/
+ }
+ else if (contentType == XMLElementDecl.TYPE_SIMPLE) {
+
+ //REVISIT
+ // this should never be reached in the case of DTD validation.
+
+ }
+ else {
+ //REVISIT
+ /****
+ fErrorReporter.reportError(fErrorReporter.getLocator(),
+ ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
+ ImplementationMessages.VAL_CST,
+ 0,
+ null,
+ XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
+ /****/
+ }
+
+ // We succeeded
+ return -1;
+
+ } // checkContent(int,int,QName[]):int
+
+ /** Returns the content spec type for an element index. */
+ private int getContentSpecType(int elementIndex) {
+
+ int contentSpecType = -1;
+ if (elementIndex > -1) {
+ if (fDTDGrammar.getElementDecl(elementIndex,fTempElementDecl)) {
+ contentSpecType = fTempElementDecl.type;
+ }
+ }
+ return contentSpecType;
+ }
+
+ /** Character data in content. */
+ private void charDataInContent() {
+
+ if (DEBUG_ELEMENT_CHILDREN) {
+ System.out.println("charDataInContent()");
+ }
+ if (fElementChildren.length <= fElementChildrenLength) {
+ QName[] newarray = new QName[fElementChildren.length * 2];
+ System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
+ fElementChildren = newarray;
+ }
+ QName qname = fElementChildren[fElementChildrenLength];
+ if (qname == null) {
+ for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
+ fElementChildren[i] = new QName();
+ }
+ qname = fElementChildren[fElementChildrenLength];
+ }
+ qname.clear();
+ fElementChildrenLength++;
+
+ } // charDataInCount()
+
+ /** convert attribute type from ints to strings */
+ private String getAttributeTypeName(XMLAttributeDecl attrDecl) {
+
+ switch (attrDecl.simpleType.type) {
+ case XMLSimpleType.TYPE_ENTITY: {
+ return attrDecl.simpleType.list ? XMLSymbols.fENTITIESSymbol : XMLSymbols.fENTITYSymbol;
+ }
+ case XMLSimpleType.TYPE_ENUMERATION: {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('(');
+ for (int i=0; i 0) {
+ buffer.append('|');
+ }
+ buffer.append(attrDecl.simpleType.enumeration[i]);
+ }
+ buffer.append(')');
+ return fSymbolTable.addSymbol(buffer.toString());
+ }
+ case XMLSimpleType.TYPE_ID: {
+ return XMLSymbols.fIDSymbol;
+ }
+ case XMLSimpleType.TYPE_IDREF: {
+ return attrDecl.simpleType.list ? XMLSymbols.fIDREFSSymbol : XMLSymbols.fIDREFSymbol;
+ }
+ case XMLSimpleType.TYPE_NMTOKEN: {
+ return attrDecl.simpleType.list ? XMLSymbols.fNMTOKENSSymbol : XMLSymbols.fNMTOKENSymbol;
+ }
+ case XMLSimpleType.TYPE_NOTATION: {
+ return XMLSymbols.fNOTATIONSymbol;
+ }
+ }
+ return XMLSymbols.fCDATASymbol;
+
+ } // getAttributeTypeName(XMLAttributeDecl):String
+
+ /** initialization */
+ protected void init() {
+
+ // datatype validators
+ if (fValidation || fDynamicValidation) {
+ try {
+ //REVISIT: datatypeRegistry + initialization of datatype
+ // why do we cast to ListDatatypeValidator?
+ fValID = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDSymbol);
+ fValIDRef = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDREFSymbol);
+ fValIDRefs = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDREFSSymbol);
+ fValENTITY = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fENTITYSymbol);
+ fValENTITIES = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fENTITIESSymbol);
+ fValNMTOKEN = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNMTOKENSymbol);
+ fValNMTOKENS = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNMTOKENSSymbol);
+ fValNOTATION = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNOTATIONSymbol);
+
+ }
+ catch (Exception e) {
+ // should never happen
+ e.printStackTrace(System.err);
+ }
+
+ }
+
+ } // init()
+
+ /** ensure element stack capacity */
+ private void ensureStackCapacity (int newElementDepth) {
+ if (newElementDepth == fElementQNamePartsStack.length) {
+
+ QName[] newStackOfQueue = new QName[newElementDepth * 2];
+ System.arraycopy(this.fElementQNamePartsStack, 0, newStackOfQueue, 0, newElementDepth );
+ fElementQNamePartsStack = newStackOfQueue;
+
+ QName qname = fElementQNamePartsStack[newElementDepth];
+ if (qname == null) {
+ for (int i = newElementDepth; i < fElementQNamePartsStack.length; i++) {
+ fElementQNamePartsStack[i] = new QName();
+ }
+ }
+
+ int[] newStack = new int[newElementDepth * 2];
+ System.arraycopy(fElementIndexStack, 0, newStack, 0, newElementDepth);
+ fElementIndexStack = newStack;
+
+ newStack = new int[newElementDepth * 2];
+ System.arraycopy(fContentSpecTypeStack, 0, newStack, 0, newElementDepth);
+ fContentSpecTypeStack = newStack;
+
+ }
+ } // ensureStackCapacity
+
+
+ //
+ // Protected methods
+ //
+
+ /** Handle element
+ * @return true if validator is removed from the pipeline
+ */
+ protected boolean handleStartElement(QName element, XMLAttributes attributes, Augmentations augs)
+ throws XNIException {
+
+
+ // VC: Root Element Type
+ // see if the root element's name matches the one in DoctypeDecl
+ if (!fSeenRootElement) {
+ // REVISIT: Here are current assumptions about validation features
+ // given that XMLSchema validator is in the pipeline
+ //
+ // http://xml.org/sax/features/validation = true
+ // http://apache.org/xml/features/validation/schema = true
+ //
+ // [1] XML instance document only has reference to a DTD
+ // Outcome: report validation errors only against dtd.
+ //
+ // [2] XML instance document has only XML Schema grammars:
+ // Outcome: report validation errors only against schemas (no errors produced from DTD validator)
+ //
+ // [3] XML instance document has DTD and XML schemas:
+ // [a] if schema language is not set outcome - validation errors reported against both grammars: DTD and schemas.
+ // [b] if schema language is set to XML Schema - do not report validation errors
+ //
+ // if dynamic validation is on
+ // validate only against grammar we've found (depending on settings
+ // for schema feature)
+ //
+ //
+ fPerformValidation = validate();
+ fSeenRootElement = true;
+ fValidationManager.setEntityState(fDTDGrammar);
+ fValidationManager.setGrammarFound(fSeenDoctypeDecl);
+ rootElementSpecified(element);
+ }
+ if (fDTDGrammar == null) {
+
+ if (!fPerformValidation) {
+ fCurrentElementIndex = -1;
+ fCurrentContentSpecType = -1;
+ fInElementContent = false;
+ }
+ if (fPerformValidation) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_GRAMMAR_NOT_FOUND",
+ new Object[]{ element.rawname},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ // modify pipeline
+ if (fDocumentSource !=null ) {
+ fDocumentSource.setDocumentHandler(fDocumentHandler);
+ if (fDocumentHandler != null)
+ fDocumentHandler.setDocumentSource(fDocumentSource);
+ return true;
+ }
+ }
+ else {
+ // resolve the element
+ fCurrentElementIndex = fDTDGrammar.getElementDeclIndex(element);
+ //changed here.. new function for getContentSpecType
+ fCurrentContentSpecType = fDTDGrammar.getContentSpecType(fCurrentElementIndex);
+ if (fCurrentContentSpecType == -1 && fPerformValidation) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_ELEMENT_NOT_DECLARED",
+ new Object[]{ element.rawname},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+
+ // 0. insert default attributes
+ // 1. normalize the attributes
+ // 2. validate the attrivute list.
+ // TO DO:
+ //changed here.. also pass element name,
+ addDTDDefaultAttrsAndValidate(element, fCurrentElementIndex, attributes);
+ }
+
+ // set element content state
+ fInElementContent = fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN;
+
+ // increment the element depth, add this element's
+ // QName to its enclosing element 's children list
+ fElementDepth++;
+ if (fPerformValidation) {
+ // push current length onto stack
+ if (fElementChildrenOffsetStack.length <= fElementDepth) {
+ int newarray[] = new int[fElementChildrenOffsetStack.length * 2];
+ System.arraycopy(fElementChildrenOffsetStack, 0, newarray, 0, fElementChildrenOffsetStack.length);
+ fElementChildrenOffsetStack = newarray;
+ }
+ fElementChildrenOffsetStack[fElementDepth] = fElementChildrenLength;
+
+ // add this element to children
+ if (fElementChildren.length <= fElementChildrenLength) {
+ QName[] newarray = new QName[fElementChildrenLength * 2];
+ System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
+ fElementChildren = newarray;
+ }
+ QName qname = fElementChildren[fElementChildrenLength];
+ if (qname == null) {
+ for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
+ fElementChildren[i] = new QName();
+ }
+ qname = fElementChildren[fElementChildrenLength];
+ }
+ qname.setValues(element);
+ fElementChildrenLength++;
+ }
+
+ // save current element information
+ fCurrentElement.setValues(element);
+ ensureStackCapacity(fElementDepth);
+ fElementQNamePartsStack[fElementDepth].setValues(fCurrentElement);
+ fElementIndexStack[fElementDepth] = fCurrentElementIndex;
+ fContentSpecTypeStack[fElementDepth] = fCurrentContentSpecType;
+ startNamespaceScope(element, attributes, augs);
+ return false;
+
+ } // handleStartElement(QName,XMLAttributes)
+
+ protected void startNamespaceScope(QName element, XMLAttributes attributes, Augmentations augs){
+ }
+
+ /** Handle end element. */
+ protected void handleEndElement(QName element, Augmentations augs, boolean isEmpty)
+ throws XNIException {
+
+ // decrease element depth
+ fElementDepth--;
+
+ // validate
+ if (fPerformValidation) {
+ int elementIndex = fCurrentElementIndex;
+ if (elementIndex != -1 && fCurrentContentSpecType != -1) {
+ QName children[] = fElementChildren;
+ int childrenOffset = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
+ int childrenLength = fElementChildrenLength - childrenOffset;
+ int result = checkContent(elementIndex,
+ children, childrenOffset, childrenLength);
+
+ if (result != -1) {
+ fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
+ if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ "MSG_CONTENT_INVALID",
+ new Object[]{ element.rawname, "EMPTY"},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ else {
+ String messageKey = result != childrenLength ?
+ "MSG_CONTENT_INVALID" : "MSG_CONTENT_INCOMPLETE";
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+ messageKey,
+ new Object[]{ element.rawname,
+ fDTDGrammar.getContentSpecAsString(elementIndex)},
+ XMLErrorReporter.SEVERITY_ERROR);
+ }
+ }
+ }
+ fElementChildrenLength = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
+ }
+
+ endNamespaceScope(fCurrentElement, augs, isEmpty);
+
+ // now pop this element off the top of the element stack
+ if (fElementDepth < -1) {
+ throw new RuntimeException("FWK008 Element stack underflow");
+ }
+ if (fElementDepth < 0) {
+ fCurrentElement.clear();
+ fCurrentElementIndex = -1;
+ fCurrentContentSpecType = -1;
+ fInElementContent = false;
+
+ // TO DO : fix this
+ //
+ // Check after document is fully parsed
+ // (1) check that there was an element with a matching id for every
+ // IDREF and IDREFS attr (V_IDREF0)
+ //
+ if (fPerformValidation) {
+ Iterator invIdRefs = fValidationState.checkIDRefID();
+ if (invIdRefs != null) {
+ while (invIdRefs.hasNext()) {
+ fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
+ "MSG_ELEMENT_WITH_ID_REQUIRED",
+ new Object[]{invIdRefs.next()},
+ XMLErrorReporter.SEVERITY_ERROR );
+ }
+ }
+ }
+ return;
+ }
+
+ // If Namespace enable then localName != rawName
+ fCurrentElement.setValues(fElementQNamePartsStack[fElementDepth]);
+
+ fCurrentElementIndex = fElementIndexStack[fElementDepth];
+ fCurrentContentSpecType = fContentSpecTypeStack[fElementDepth];
+ fInElementContent = (fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN);
+
+ } // handleEndElement(QName,boolean)
+
+ protected void endNamespaceScope(QName element, Augmentations augs, boolean isEmpty){
+
+ // call handlers
+ if (fDocumentHandler != null && !isEmpty) {
+ // NOTE: The binding of the element doesn't actually happen
+ // yet because the namespace binder does that. However,
+ // if it does it before this point, then the endPrefix-
+ // Mapping calls get made too soon! As long as the
+ // rawnames match, we know it'll have a good binding,
+ // so we can just use the current element. -Ac
+ fDocumentHandler.endElement(fCurrentElement, augs);
+ }
+ }
+
+ // returns whether a character is space according to the
+ // version of XML this validator supports.
+ protected boolean isSpace(int c) {
+ return XMLChar.isSpace(c);
+ } // isSpace(int): boolean
+
+ public boolean characterData(String data, Augmentations augs) {
+ characters(new XMLString(data.toCharArray(), 0, data.length()), augs);
+ return true;
+ }
+
+} // class XMLDTDValidator
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDValidatorFilter.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDValidatorFilter.java
new file mode 100644
index 0000000..164018d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLDTDValidatorFilter.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import org.apache.xerces.xni.parser.XMLDocumentFilter;
+
+/**
+ * Defines a DTD Validator filter to allow
+ * components to query the DTD validator.
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani, IBM
+ *
+ * @version $Id$
+ */
+public interface XMLDTDValidatorFilter
+ extends XMLDocumentFilter {
+
+ /**
+ * Returns true if the validator has a DTD grammar
+ *
+ * @return true if the validator has a DTD grammar
+ */
+ public boolean hasGrammar();
+
+ /**
+ * Return true if validator must validate the document
+ *
+ * @return true if validator must validate the document
+ */
+ public boolean validate();
+
+
+} // interface XMLDTDValidatorFilter
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLElementDecl.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLElementDecl.java
new file mode 100644
index 0000000..0c59976
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLElementDecl.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import org.apache.xerces.impl.dtd.models.ContentModelValidator;
+import org.apache.xerces.xni.QName;
+
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class XMLElementDecl {
+
+ //
+ // Constants
+ //
+
+ /** TYPE_ANY */
+ public static final short TYPE_ANY = 0;
+
+ /** TYPE_EMPTY */
+ public static final short TYPE_EMPTY = 1;
+
+ /** TYPE_MIXED */
+ public static final short TYPE_MIXED = 2;
+
+ /** TYPE_CHILDREN */
+ public static final short TYPE_CHILDREN = 3;
+
+ /** TYPE_SIMPLE */
+ public static final short TYPE_SIMPLE = 4;
+
+ //
+ // Data
+ //
+
+ /** name */
+ public final QName name = new QName();
+
+ /** scope */
+ public int scope = -1;
+
+ /** type */
+ public short type = -1;
+
+ /** contentModelValidator */
+ public ContentModelValidator contentModelValidator;
+
+ /** simpleType */
+ public final XMLSimpleType simpleType = new XMLSimpleType();
+
+ //
+ // Methods
+ //
+
+ /**
+ * setValues
+ *
+ * @param name
+ * @param scope
+ * @param type
+ * @param contentModelValidator
+ * @param simpleType
+ */
+ public void setValues(QName name, int scope, short type, ContentModelValidator contentModelValidator, XMLSimpleType simpleType) {
+ this.name.setValues(name);
+ this.scope = scope;
+ this.type = type;
+ this.contentModelValidator = contentModelValidator;
+ this.simpleType.setValues(simpleType);
+ } // setValues
+
+ /**
+ * clear
+ */
+ public void clear() {
+ this.name.clear();
+ this.type = -1;
+ this.scope = -1;
+ this.contentModelValidator = null;
+ this.simpleType.clear();
+ } // clear
+
+} // class XMLElementDecl
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLEntityDecl.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLEntityDecl.java
new file mode 100644
index 0000000..1d07157
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLEntityDecl.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class XMLEntityDecl {
+
+ //
+ // Data
+ //
+
+ /** name */
+ public String name;
+
+ /** publicId */
+ public String publicId;
+
+ /** systemId */
+ public String systemId;
+
+ /** baseSystemId */
+ public String baseSystemId;
+
+ /** notation */
+ public String notation;
+
+ /** isPE */
+ public boolean isPE;
+
+ /** inExternal */
+ /** Note: flag of where the entity is defined, not whether it is a external entity */
+ public boolean inExternal;
+
+ /** Value. */
+ public String value;
+
+ //
+ // Methods
+ //
+
+ /**
+ * setValues
+ *
+ * @param name
+ * @param publicId
+ * @param systemId
+ * @param baseSystemId
+ * @param notation
+ * @param isPE
+ * @param inExternal
+ */
+ public void setValues(String name, String publicId, String systemId,
+ String baseSystemId, String notation,
+ boolean isPE, boolean inExternal) {
+ setValues(name, publicId, systemId, baseSystemId, notation, null, isPE, inExternal);
+ }
+
+ /**
+ * setValues
+ *
+ * @param name
+ * @param publicId
+ * @param systemId
+ * @param baseSystemId
+ * @param value
+ * @param notation
+ * @param isPE
+ * @param inExternal
+ */
+ public void setValues(String name, String publicId, String systemId,
+ String baseSystemId, String notation,
+ String value, boolean isPE, boolean inExternal) {
+ this.name = name;
+ this.publicId = publicId;
+ this.systemId = systemId;
+ this.baseSystemId = baseSystemId;
+ this.notation = notation;
+ this.value = value;
+ this.isPE = isPE;
+ this.inExternal = inExternal;
+ } // setValues(String,String,String,String,String,boolean,boolean)
+
+ /**
+ * clear
+ */
+ public void clear() {
+ this.name = null;
+ this.publicId = null;
+ this.systemId = null;
+ this.baseSystemId = null;
+ this.notation = null;
+ this.value = null;
+ this.isPE = false;
+ this.inExternal = false;
+
+ } // clear
+
+} // class XMLEntityDecl
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLNSDTDValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLNSDTDValidator.java
new file mode 100644
index 0000000..f32d1b9
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLNSDTDValidator.java
@@ -0,0 +1,230 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import org.apache.xerces.impl.XMLErrorReporter;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLAttributes;
+import org.apache.xerces.xni.XNIException;
+
+
+/**
+ * The DTD validator. The validator implements a document
+ * filter: receiving document events from the scanner; validating
+ * the content and structure; augmenting the InfoSet, if applicable;
+ * and notifying the parser of the information resulting from the
+ * validation process.
+ * Formerly, this component also handled DTD events and grammar construction.
+ * To facilitate the development of a meaningful DTD grammar caching/preparsing
+ * framework, this functionality has been moved into the XMLDTDLoader
+ * class. Therefore, this class no longer implements the DTDFilter
+ * or DTDContentModelFilter interfaces.
+ *
+ * This component requires the following features and properties from the
+ * component manager that uses it:
+ *
+ * - http://xml.org/sax/features/namespaces
+ * - http://xml.org/sax/features/validation
+ * - http://apache.org/xml/features/validation/dynamic
+ * - http://apache.org/xml/properties/internal/symbol-table
+ * - http://apache.org/xml/properties/internal/error-reporter
+ * - http://apache.org/xml/properties/internal/grammar-pool
+ * - http://apache.org/xml/properties/internal/datatype-validator-factory
+ *
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani, IBM
+ *
+ * @version $Id$
+ */
+public class XMLNSDTDValidator
+ extends XMLDTDValidator{
+
+ /** Attribute QName. */
+ private final QName fAttributeQName = new QName();
+
+ /** Bind namespaces */
+ protected final void startNamespaceScope (QName element, XMLAttributes attributes,
+ Augmentations augs) throws XNIException {
+
+ // add new namespace context
+ fNamespaceContext.pushContext();
+
+ if (element.prefix == XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementXMLNSPrefix",
+ new Object[]{element.rawname},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // search for new namespace bindings
+ int length = attributes.getLength();
+ for (int i = 0; i < length; i++) {
+ String localpart = attributes.getLocalName(i);
+ String prefix = attributes.getPrefix(i);
+ // when it's of form xmlns="..." or xmlns:prefix="...",
+ // it's a namespace declaration. but prefix:xmlns="..." isn't.
+ if (prefix == XMLSymbols.PREFIX_XMLNS ||
+ prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) {
+
+ // get the internalized value of this attribute
+ String uri = fSymbolTable.addSymbol(attributes.getValue(i));
+
+ // 1. "xmlns" can't be bound to any namespace
+ if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXMLNS",
+ new Object[]{attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // 2. the namespace for "xmlns" can't be bound to any prefix
+ if (uri == NamespaceContext.XMLNS_URI) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXMLNS",
+ new Object[]{attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // 3. "xml" can't be bound to any other namespace than it's own
+ if (localpart == XMLSymbols.PREFIX_XML) {
+ if (uri != NamespaceContext.XML_URI) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXML",
+ new Object[]{attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ // 4. the namespace for "xml" can't be bound to any other prefix
+ else {
+ if (uri ==NamespaceContext.XML_URI) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "CantBindXML",
+ new Object[]{attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+
+ prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING;
+
+ // http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix
+ // We should only report an error if there is a prefix,
+ // that is, the local part is not "xmlns". -SG
+ if (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "EmptyPrefixedAttName",
+ new Object[]{attributes.getQName(i)},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ continue;
+ }
+
+ // declare prefix in context
+ fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null);
+ }
+ }
+
+ // bind the element
+ String prefix = element.prefix != null
+ ? element.prefix : XMLSymbols.EMPTY_STRING;
+ element.uri = fNamespaceContext.getURI(prefix);
+ if (element.prefix == null && element.uri != null) {
+ element.prefix = XMLSymbols.EMPTY_STRING;
+ }
+ if (element.prefix != null && element.uri == null) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "ElementPrefixUnbound",
+ new Object[]{element.prefix, element.rawname},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+
+ // bind the attributes
+ for (int i = 0; i < length; i++) {
+ attributes.getName(i, fAttributeQName);
+ String aprefix = fAttributeQName.prefix != null
+ ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
+ String arawname = fAttributeQName.rawname;
+ if (arawname == XMLSymbols.PREFIX_XMLNS) {
+ fAttributeQName.uri = fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS);
+ attributes.setName(i, fAttributeQName);
+ }
+ else if (aprefix != XMLSymbols.EMPTY_STRING) {
+ fAttributeQName.uri = fNamespaceContext.getURI(aprefix);
+ if (fAttributeQName.uri == null) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributePrefixUnbound",
+ new Object[]{element.rawname,arawname,aprefix},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ attributes.setName(i, fAttributeQName);
+ }
+ }
+
+ // verify that duplicate attributes don't exist
+ // Example:
+ int attrCount = attributes.getLength();
+ for (int i = 0; i < attrCount - 1; i++) {
+ String auri = attributes.getURI(i);
+ if (auri == null || auri == NamespaceContext.XMLNS_URI) {
+ continue;
+ }
+ String alocalpart = attributes.getLocalName(i);
+ for (int j = i + 1; j < attrCount; j++) {
+ String blocalpart = attributes.getLocalName(j);
+ String buri = attributes.getURI(j);
+ if (alocalpart == blocalpart && auri == buri) {
+ fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
+ "AttributeNSNotUnique",
+ new Object[]{element.rawname,alocalpart, auri},
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ }
+ }
+
+
+ } // startNamespaceScope(QName,XMLAttributes)
+
+
+ /** Handles end element. */
+ protected void endNamespaceScope(QName element, Augmentations augs, boolean isEmpty)
+ throws XNIException {
+
+ // bind element
+ String eprefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING;
+ element.uri = fNamespaceContext.getURI(eprefix);
+ if (element.uri != null) {
+ element.prefix = eprefix;
+ }
+
+ // call handlers
+ if (fDocumentHandler != null) {
+ if (!isEmpty) {
+ fDocumentHandler.endElement(element, augs);
+ }
+ }
+
+ // pop context
+ fNamespaceContext.popContext();
+
+ } // endNamespaceScope(QName,boolean)
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLNotationDecl.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLNotationDecl.java
new file mode 100644
index 0000000..abfaac5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLNotationDecl.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class XMLNotationDecl {
+
+ //
+ // Data
+ //
+
+ /** name */
+ public String name;
+
+ /** publicId */
+ public String publicId;
+
+ /** systemId */
+ public String systemId;
+
+ /** base systemId */
+ public String baseSystemId;
+
+ //
+ // Methods
+ //
+
+ /**
+ * setValues
+ *
+ * @param name
+ * @param publicId
+ * @param systemId
+ */
+ public void setValues(String name, String publicId, String systemId, String baseSystemId) {
+ this.name = name;
+ this.publicId = publicId;
+ this.systemId = systemId;
+ this.baseSystemId = baseSystemId;
+ } // setValues
+
+ /**
+ * clear
+ */
+ public void clear() {
+ this.name = null;
+ this.publicId = null;
+ this.systemId = null;
+ this.baseSystemId = null;
+ } // clear
+
+} // class XMLNotationDecl
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLSimpleType.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLSimpleType.java
new file mode 100644
index 0000000..841ff1d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/XMLSimpleType.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd;
+
+import org.apache.xerces.impl.dv.DatatypeValidator;
+
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class XMLSimpleType {
+
+ //
+ // Constants
+ //
+
+ /** TYPE_CDATA */
+ public static final short TYPE_CDATA = 0;
+
+ /** TYPE_ENTITY */
+ public static final short TYPE_ENTITY = 1;
+
+ /** TYPE_ENUMERATION */
+ public static final short TYPE_ENUMERATION = 2;
+
+ /** TYPE_ID */
+ public static final short TYPE_ID = 3;
+
+ /** TYPE_IDREF */
+ public static final short TYPE_IDREF = 4;
+
+ /** TYPE_NMTOKEN */
+ public static final short TYPE_NMTOKEN = 5;
+
+ /** TYPE_NOTATION */
+ public static final short TYPE_NOTATION = 6;
+
+ /** TYPE_NAMED */
+ public static final short TYPE_NAMED = 7;
+
+ /** DEFAULT_TYPE_DEFAULT */
+ public static final short DEFAULT_TYPE_DEFAULT = 3;
+
+ /** DEFAULT_TYPE_FIXED */
+ public static final short DEFAULT_TYPE_FIXED = 1;
+
+ /** DEFAULT_TYPE_IMPLIED */
+ public static final short DEFAULT_TYPE_IMPLIED = 0;
+
+ /** DEFAULT_TYPE_REQUIRED */
+ public static final short DEFAULT_TYPE_REQUIRED = 2;
+
+ //
+ // Data
+ //
+
+ /** type */
+ public short type;
+
+ /** name */
+ public String name;
+
+ /** enumeration */
+ public String[] enumeration;
+
+ /** list */
+ public boolean list;
+
+ /** defaultType */
+ public short defaultType;
+
+ /** defaultValue */
+ public String defaultValue;
+
+ /** non-normalized defaultValue */
+ public String nonNormalizedDefaultValue;
+
+ /** datatypeValidator */
+ public DatatypeValidator datatypeValidator;
+
+ //
+ // Methods
+ //
+
+ /**
+ * setValues
+ *
+ * @param type
+ * @param name
+ * @param enumeration
+ * @param list
+ * @param defaultType
+ * @param defaultValue
+ * @param nonNormalizedDefaultValue
+ * @param datatypeValidator
+ */
+ public void setValues(short type, String name, String[] enumeration,
+ boolean list, short defaultType,
+ String defaultValue, String nonNormalizedDefaultValue,
+ DatatypeValidator datatypeValidator) {
+
+ this.type = type;
+ this.name = name;
+ // REVISIT: Should this be a copy? -Ac
+ if (enumeration != null && enumeration.length > 0) {
+ this.enumeration = new String[enumeration.length];
+ System.arraycopy(enumeration, 0, this.enumeration, 0, this.enumeration.length);
+ }
+ else {
+ this.enumeration = null;
+ }
+ this.list = list;
+ this.defaultType = defaultType;
+ this.defaultValue = defaultValue;
+ this.nonNormalizedDefaultValue = nonNormalizedDefaultValue;
+ this.datatypeValidator = datatypeValidator;
+
+ } // setValues(short,String,String[],boolean,short,String,String,DatatypeValidator)
+
+ /** Set values. */
+ public void setValues(XMLSimpleType simpleType) {
+
+ type = simpleType.type;
+ name = simpleType.name;
+ // REVISIT: Should this be a copy? -Ac
+ if (simpleType.enumeration != null && simpleType.enumeration.length > 0) {
+ enumeration = new String[simpleType.enumeration.length];
+ System.arraycopy(simpleType.enumeration, 0, enumeration, 0, enumeration.length);
+ }
+ else {
+ enumeration = null;
+ }
+ list = simpleType.list;
+ defaultType = simpleType.defaultType;
+ defaultValue = simpleType.defaultValue;
+ nonNormalizedDefaultValue = simpleType.nonNormalizedDefaultValue;
+ datatypeValidator = simpleType.datatypeValidator;
+
+ } // setValues(XMLSimpleType)
+
+ /**
+ * clear
+ */
+ public void clear() {
+ this.type = -1;
+ this.name = null;
+ this.enumeration = null;
+ this.list = false;
+ this.defaultType = -1;
+ this.defaultValue = null;
+ this.nonNormalizedDefaultValue = null;
+ this.datatypeValidator = null;
+ } // clear
+
+} // class XMLSimpleType
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMAny.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMAny.java
new file mode 100644
index 0000000..ed6d007
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMAny.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd.models;
+
+
+/**
+ * Content model any node.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class CMAny
+ extends CMNode {
+
+ //
+ // Data
+ //
+
+ /**
+ * The any content model type. This value is one of the following:
+ * XMLContentSpec.CONTENTSPECNODE_ANY,
+ * XMLContentSpec.CONTENTSPECNODE_ANY_OTHER,
+ * XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL.
+ */
+ private final int fType;
+
+ /**
+ * URI of the any content model. This value is set if the type is
+ * of the following:
+ * XMLContentSpec.CONTENTSPECNODE_ANY,
+ * XMLContentSpec.CONTENTSPECNODE_ANY_OTHER.
+ */
+ private final String fURI;
+
+ /**
+ * Part of the algorithm to convert a regex directly to a DFA
+ * numbers each leaf sequentially. If its -1, that means its an
+ * epsilon node. Zero and greater are non-epsilon positions.
+ */
+ private int fPosition = -1;
+
+ //
+ // Constructors
+ //
+
+ /** Constructs a content model any. */
+ public CMAny(int type, String uri, int position) {
+ super(type);
+
+ // Store the information
+ fType = type;
+ fURI = uri;
+ fPosition = position;
+ }
+
+ //
+ // Package methods
+ //
+
+ final int getType() {
+ return fType;
+ }
+
+ final String getURI() {
+ return fURI;
+ }
+
+ final int getPosition()
+ {
+ return fPosition;
+ }
+
+ final void setPosition(int newPosition)
+ {
+ fPosition = newPosition;
+ }
+
+ //
+ // CMNode methods
+ //
+
+ // package
+
+ public boolean isNullable()
+ {
+ // Leaf nodes are never nullable unless its an epsilon node
+ return (fPosition == -1);
+ }
+
+ public String toString()
+ {
+ StringBuffer strRet = new StringBuffer();
+ strRet.append('(');
+ strRet.append("##any:uri=");
+ strRet.append(fURI);
+ strRet.append(')');
+ if (fPosition >= 0) {
+ strRet.append(" (Pos:")
+ .append(Integer.toString(fPosition))
+ .append(')');
+ }
+ return strRet.toString();
+ }
+
+ // protected
+
+ protected void calcFirstPos(CMStateSet toSet)
+ {
+ // If we are an epsilon node, then the first pos is an empty set
+ if (fPosition == -1)
+ toSet.zeroBits();
+
+ // Otherwise, its just the one bit of our position
+ else
+ toSet.setBit(fPosition);
+ }
+
+ protected void calcLastPos(CMStateSet toSet)
+ {
+ // If we are an epsilon node, then the last pos is an empty set
+ if (fPosition == -1)
+ toSet.zeroBits();
+
+ // Otherwise, its just the one bit of our position
+ else
+ toSet.setBit(fPosition);
+ }
+
+} // class CMAny
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMBinOp.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMBinOp.java
new file mode 100644
index 0000000..ce24934
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMBinOp.java
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd.models;
+
+import org.apache.xerces.impl.dtd.XMLContentSpec;
+
+/**
+ * Content model Bin-Op node.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class CMBinOp extends CMNode
+{
+ // -------------------------------------------------------------------
+ // Constructors
+ // -------------------------------------------------------------------
+ public CMBinOp(int type, CMNode leftNode, CMNode rightNode)
+ {
+ super(type);
+
+ // Insure that its one of the types we require
+ if ((type() != XMLContentSpec.CONTENTSPECNODE_CHOICE)
+ && (type() != XMLContentSpec.CONTENTSPECNODE_SEQ))
+ {
+ throw new RuntimeException("ImplementationMessages.VAL_BST");
+ }
+
+ // Store the nodes and init any data that needs it
+ fLeftChild = leftNode;
+ fRightChild = rightNode;
+ }
+
+
+ // -------------------------------------------------------------------
+ // Package, final methods
+ // -------------------------------------------------------------------
+ final CMNode getLeft()
+ {
+ return fLeftChild;
+ }
+
+ final CMNode getRight()
+ {
+ return fRightChild;
+ }
+
+
+ // -------------------------------------------------------------------
+ // Package, inherited methods
+ // -------------------------------------------------------------------
+ public boolean isNullable()
+ {
+ //
+ // If its an alternation, then if either child is nullable then
+ // this node is nullable. If its a concatenation, then both of
+ // them have to be nullable.
+ //
+ if (type() == XMLContentSpec.CONTENTSPECNODE_CHOICE)
+ return (fLeftChild.isNullable() || fRightChild.isNullable());
+ else if (type() == XMLContentSpec.CONTENTSPECNODE_SEQ)
+ return (fLeftChild.isNullable() && fRightChild.isNullable());
+ else
+ throw new RuntimeException("ImplementationMessages.VAL_BST");
+ }
+
+
+ // -------------------------------------------------------------------
+ // Protected, inherited methods
+ // -------------------------------------------------------------------
+ protected void calcFirstPos(CMStateSet toSet)
+ {
+ if (type() == XMLContentSpec.CONTENTSPECNODE_CHOICE)
+ {
+ // Its the the union of the first positions of our children.
+ toSet.setTo(fLeftChild.firstPos());
+ toSet.union(fRightChild.firstPos());
+ }
+ else if (type() == XMLContentSpec.CONTENTSPECNODE_SEQ)
+ {
+ //
+ // If our left child is nullable, then its the union of our
+ // children's first positions. Else is our left child's first
+ // positions.
+ //
+ toSet.setTo(fLeftChild.firstPos());
+ if (fLeftChild.isNullable())
+ toSet.union(fRightChild.firstPos());
+ }
+ else
+ {
+ throw new RuntimeException("ImplementationMessages.VAL_BST");
+ }
+ }
+
+ protected void calcLastPos(CMStateSet toSet)
+ {
+ if (type() == XMLContentSpec.CONTENTSPECNODE_CHOICE)
+ {
+ // Its the the union of the first positions of our children.
+ toSet.setTo(fLeftChild.lastPos());
+ toSet.union(fRightChild.lastPos());
+ }
+ else if (type() == XMLContentSpec.CONTENTSPECNODE_SEQ)
+ {
+ //
+ // If our right child is nullable, then its the union of our
+ // children's last positions. Else is our right child's last
+ // positions.
+ //
+ toSet.setTo(fRightChild.lastPos());
+ if (fRightChild.isNullable())
+ toSet.union(fLeftChild.lastPos());
+ }
+ else
+ {
+ throw new RuntimeException("ImplementationMessages.VAL_BST");
+ }
+ }
+
+
+ // -------------------------------------------------------------------
+ // Private data members
+ //
+ // fLeftChild
+ // fRightChild
+ // These are the references to the two nodes that are on either
+ // side of this binary operation.
+ // -------------------------------------------------------------------
+ private final CMNode fLeftChild;
+ private final CMNode fRightChild;
+};
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMLeaf.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMLeaf.java
new file mode 100644
index 0000000..12e80b1
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMLeaf.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd.models;
+
+import org.apache.xerces.impl.dtd.XMLContentSpec;
+import org.apache.xerces.xni.QName;
+
+/**
+ * Content model leaf node.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class CMLeaf
+ extends CMNode {
+
+ //
+ // Data
+ //
+
+ /** This is the element that this leaf represents. */
+ private final QName fElement = new QName();
+
+ /**
+ * Part of the algorithm to convert a regex directly to a DFA
+ * numbers each leaf sequentially. If its -1, that means its an
+ * epsilon node. Zero and greater are non-epsilon positions.
+ */
+ private int fPosition = -1;
+
+ //
+ // Constructors
+ //
+
+ /** Constructs a content model leaf. */
+ public CMLeaf(QName element, int position) {
+ super(XMLContentSpec.CONTENTSPECNODE_LEAF);
+
+ // Store the element index and position
+ fElement.setValues(element);
+ fPosition = position;
+ }
+
+ /** Constructs a content model leaf. */
+ public CMLeaf(QName element) {
+ super(XMLContentSpec.CONTENTSPECNODE_LEAF);
+
+ // Store the element index and position
+ fElement.setValues(element);
+ }
+
+ //
+ // Package methods
+ //
+
+ final QName getElement()
+ {
+ return fElement;
+ }
+
+ final int getPosition()
+ {
+ return fPosition;
+ }
+
+ final void setPosition(int newPosition)
+ {
+ fPosition = newPosition;
+ }
+
+ //
+ // CMNode methods
+ //
+
+ // package
+
+ public boolean isNullable()
+ {
+ // Leaf nodes are never nullable unless its an epsilon node
+ return (fPosition == -1);
+ }
+
+ public String toString()
+ {
+ StringBuffer strRet = new StringBuffer(fElement.toString());
+ strRet.append(" (");
+ strRet.append(fElement.uri);
+ strRet.append(',');
+ strRet.append(fElement.localpart);
+ strRet.append(')');
+ if (fPosition >= 0) {
+ strRet.append(" (Pos:")
+ .append(Integer.toString(fPosition))
+ .append(')');
+ }
+ return strRet.toString();
+ }
+
+ // protected
+
+ protected void calcFirstPos(CMStateSet toSet)
+ {
+ // If we are an epsilon node, then the first pos is an empty set
+ if (fPosition == -1)
+ toSet.zeroBits();
+
+ // Otherwise, its just the one bit of our position
+ else
+ toSet.setBit(fPosition);
+ }
+
+ protected void calcLastPos(CMStateSet toSet)
+ {
+ // If we are an epsilon node, then the last pos is an empty set
+ if (fPosition == -1)
+ toSet.zeroBits();
+
+ // Otherwise, its just the one bit of our position
+ else
+ toSet.setBit(fPosition);
+ }
+
+} // class CMLeaf
+
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMNode.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMNode.java
new file mode 100644
index 0000000..3847a45
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMNode.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd.models;
+
+/**
+ * A content model node.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public abstract class CMNode
+{
+ // -------------------------------------------------------------------
+ // Constructors
+ // -------------------------------------------------------------------
+ public CMNode(int type)
+ {
+ fType = type;
+ }
+
+
+ // -------------------------------------------------------------------
+ // Package, abstract methods
+ // -------------------------------------------------------------------
+ // made this public so it could be implemented and used outside this package -neilg.
+ public abstract boolean isNullable() ;
+
+
+ // -------------------------------------------------------------------
+ // Package final methods
+ // -------------------------------------------------------------------
+ public final int type()
+ {
+ return fType;
+ }
+
+ // made this public so it could be implemented and used outside this package -neilg.
+ public final CMStateSet firstPos()
+ {
+ if (fFirstPos == null)
+ {
+ fFirstPos = new CMStateSet(fMaxStates);
+ calcFirstPos(fFirstPos);
+ }
+ return fFirstPos;
+ }
+
+ // made this public so it could be implemented and used outside this package -neilg.
+ public final CMStateSet lastPos()
+ {
+ if (fLastPos == null)
+ {
+ fLastPos = new CMStateSet(fMaxStates);
+ calcLastPos(fLastPos);
+ }
+ return fLastPos;
+ }
+
+ final void setFollowPos(CMStateSet setToAdopt)
+ {
+ fFollowPos = setToAdopt;
+ }
+
+ public final void setMaxStates(int maxStates)
+ {
+ fMaxStates = maxStates;
+ }
+
+ public boolean isCompactedForUPA() {
+ return fCompactedForUPA;
+ }
+
+ public void setIsCompactUPAModel(boolean value) {
+ fCompactedForUPA = value;
+ }
+
+
+ // -------------------------------------------------------------------
+ // Protected, abstract methods
+ // -------------------------------------------------------------------
+ protected abstract void calcFirstPos(CMStateSet toSet) ;
+
+ protected abstract void calcLastPos(CMStateSet toSet) ;
+
+
+ // -------------------------------------------------------------------
+ // Private data members
+ //
+ // fType
+ // The type of node. This indicates whether its a leaf or an
+ // operation. Though we also do derived classes for these types,
+ // it is too expensive to use runtime typing to find this out.
+ // This is one of the ContentSpecNode.NODE_XXX types.
+ //
+ // fFirstPos
+ // The set of NFA states that represent the entry states of this
+ // node in the DFA.
+ //
+ // fFollowPos
+ // The set of NFA states that can be gotten to from from this
+ // node in the DFA.
+ //
+ // fLastPos
+ // The set of NFA states that represent the final states of this
+ // node in the DFA.
+ //
+ // fMaxStates
+ // The maximum number of states that the NFA has, which means the
+ // max number of NFA states that have to be traced in the state
+ // sets during the building of the DFA. Its unfortunate that it
+ // has to be stored redundantly, but we need to fault in the
+ // state set members and they have to be sized to this size. We
+ // init to to -1 so it will cause an error if its used without
+ // being initialized.
+ // -------------------------------------------------------------------
+ private final int fType;
+ private CMStateSet fFirstPos = null;
+ private CMStateSet fFollowPos = null;
+ private CMStateSet fLastPos = null;
+ private int fMaxStates = -1;
+
+ /*
+ * This boolean is true if the model represented by the CMNode does not represent
+ * the true model from the schema, but has had its min/maxOccurs modified for a
+ * more compact representation (for purposes of UPA).
+ */
+ private boolean fCompactedForUPA = false;
+};
\ No newline at end of file
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMStateSet.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMStateSet.java
new file mode 100644
index 0000000..6fef52c
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMStateSet.java
@@ -0,0 +1,300 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd.models;
+
+
+/**
+ * This class is a very simple bitset class. The DFA content model code needs
+ * to support a bit set, but the java BitSet class is way, way overkill. Our
+ * bitset never needs to be expanded after creation, hash itself, etc...
+ *
+ * Since the vast majority of content models will never require more than 64
+ * bits, and since allocation of anything in Java is expensive, this class
+ * provides a hybrid implementation that uses two ints for instances that use
+ * 64 bits or fewer. It has a byte array reference member which will only be
+ * used if more than 64 bits are required.
+ *
+ * Note that the code that uses this class will never perform operations
+ * on sets of different sizes, so that check does not have to be made here.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+// made this class public so it can be accessed by
+// the XS content models from the schema package -neilg.
+public class CMStateSet
+{
+ // -------------------------------------------------------------------
+ // Constructors
+ // -------------------------------------------------------------------
+ public CMStateSet(int bitCount)
+ {
+ // Store the required bit count and insure its legal
+ fBitCount = bitCount;
+ if (fBitCount < 0)
+ throw new RuntimeException("ImplementationMessages.VAL_CMSI");
+
+ //
+ // See if we need to allocate the byte array or whether we can live
+ // within the 64 bit high performance scheme.
+ //
+ if (fBitCount > 64)
+ {
+ fByteCount = fBitCount / 8;
+ if (fBitCount % 8 != 0)
+ fByteCount++;
+ fByteArray = new byte[fByteCount];
+ }
+
+ // Init all the bits to zero
+ zeroBits();
+ }
+
+
+ // -------------------------------------------------------------------
+ // Public inherited methods
+ // -------------------------------------------------------------------
+ public String toString()
+ {
+ StringBuffer strRet = new StringBuffer();
+ try
+ {
+ strRet.append('{');
+ for (int index = 0; index < fBitCount; index++) {
+ if (getBit(index)) {
+ strRet.append(' ').append(index);
+ }
+ }
+ strRet.append(" }");
+ }
+
+ catch(RuntimeException exToCatch)
+ {
+ //
+ // We know this won't happen but we have to catch it to avoid it
+ // having to be in our 'throws' list.
+ //
+ }
+ return strRet.toString();
+ }
+
+
+ // -------------------------------------------------------------------
+ // Package final methods
+ // -------------------------------------------------------------------
+// the XS content models from the schema package -neilg.
+ public final void intersection(CMStateSet setToAnd)
+ {
+ if (fBitCount < 65)
+ {
+ fBits1 &= setToAnd.fBits1;
+ fBits2 &= setToAnd.fBits2;
+ }
+ else
+ {
+ for (int index = fByteCount - 1; index >= 0; index--)
+ fByteArray[index] &= setToAnd.fByteArray[index];
+ }
+ }
+
+ public final boolean getBit(int bitToGet)
+ {
+ if (bitToGet >= fBitCount)
+ throw new RuntimeException("ImplementationMessages.VAL_CMSI");
+
+ if (fBitCount < 65)
+ {
+ final int mask = (0x1 << (bitToGet % 32));
+ if (bitToGet < 32)
+ return (fBits1 & mask) != 0;
+ else
+ return (fBits2 & mask) != 0;
+ }
+ else
+ {
+ // Create the mask and byte values
+ final byte mask = (byte)(0x1 << (bitToGet % 8));
+ final int ofs = bitToGet >> 3;
+
+ // And access the right bit and byte
+ return ((fByteArray[ofs] & mask) != 0);
+ }
+ }
+
+ public final boolean isEmpty()
+ {
+ if (fBitCount < 65)
+ {
+ return ((fBits1 == 0) && (fBits2 == 0));
+ }
+ else
+ {
+ for (int index = fByteCount - 1; index >= 0; index--)
+ {
+ if (fByteArray[index] != 0)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ final boolean isSameSet(CMStateSet setToCompare)
+ {
+ if (fBitCount != setToCompare.fBitCount)
+ return false;
+
+ if (fBitCount < 65)
+ {
+ return ((fBits1 == setToCompare.fBits1)
+ && (fBits2 == setToCompare.fBits2));
+ }
+
+ for (int index = fByteCount - 1; index >= 0; index--)
+ {
+ if (fByteArray[index] != setToCompare.fByteArray[index])
+ return false;
+ }
+ return true;
+ }
+
+// the XS content models from the schema package -neilg.
+ public final void union(CMStateSet setToOr)
+ {
+ if (fBitCount < 65)
+ {
+ fBits1 |= setToOr.fBits1;
+ fBits2 |= setToOr.fBits2;
+ }
+ else
+ {
+ for (int index = fByteCount - 1; index >= 0; index--)
+ fByteArray[index] |= setToOr.fByteArray[index];
+ }
+ }
+
+ public final void setBit(int bitToSet)
+ {
+ if (bitToSet >= fBitCount)
+ throw new RuntimeException("ImplementationMessages.VAL_CMSI");
+
+ if (fBitCount < 65)
+ {
+ final int mask = (0x1 << (bitToSet % 32));
+ if (bitToSet < 32)
+ {
+ fBits1 &= ~mask;
+ fBits1 |= mask;
+ }
+ else
+ {
+ fBits2 &= ~mask;
+ fBits2 |= mask;
+ }
+ }
+ else
+ {
+ // Create the mask and byte values
+ final byte mask = (byte)(0x1 << (bitToSet % 8));
+ final int ofs = bitToSet >> 3;
+
+ // And access the right bit and byte
+ fByteArray[ofs] &= ~mask;
+ fByteArray[ofs] |= mask;
+ }
+ }
+
+// the XS content models from the schema package -neilg.
+ public final void setTo(CMStateSet srcSet)
+ {
+ // They have to be the same size
+ if (fBitCount != srcSet.fBitCount)
+ throw new RuntimeException("ImplementationMessages.VAL_CMSI");
+
+ if (fBitCount < 65)
+ {
+ fBits1 = srcSet.fBits1;
+ fBits2 = srcSet.fBits2;
+ }
+ else
+ {
+ for (int index = fByteCount - 1; index >= 0; index--)
+ fByteArray[index] = srcSet.fByteArray[index];
+ }
+ }
+
+ // had to make this method public so it could be accessed from
+ // schema package - neilg.
+ public final void zeroBits()
+ {
+ if (fBitCount < 65)
+ {
+ fBits1 = 0;
+ fBits2 = 0;
+ }
+ else
+ {
+ for (int index = fByteCount - 1; index >= 0; index--)
+ fByteArray[index] = 0;
+ }
+ }
+
+
+ // -------------------------------------------------------------------
+ // Private data members
+ //
+ // fBitCount
+ // The count of bits that the outside world wants to support,
+ // so its the max bit index plus one.
+ //
+ // fByteCount
+ // If the bit count is > 64, then we use the fByteArray member to
+ // store the bits, and this indicates its size in bytes. Otherwise
+ // its value is meaningless.
+ //
+ // fBits1
+ // fBits2
+ // When the bit count is < 64 (very common), these hold the bits.
+ // Otherwise, the fByteArray member holds htem.
+ // -------------------------------------------------------------------
+ int fBitCount;
+ int fByteCount;
+ int fBits1;
+ int fBits2;
+ byte[] fByteArray;
+ /* Optimization(Jan, 2001) */
+ public boolean equals(Object o) {
+ if (!(o instanceof CMStateSet)) return false;
+ return isSameSet((CMStateSet)o);
+ }
+
+ public int hashCode() {
+ if (fBitCount < 65)
+ {
+ return fBits1+ fBits2 * 31;
+ }
+ else
+ {
+ int hash = 0;
+ for (int index = fByteCount - 1; index >= 0; index--)
+ hash = fByteArray[index] + hash * 31;
+ return hash;
+ }
+ }
+ /* Optimization(Jan, 2001) */
+};
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMUniOp.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMUniOp.java
new file mode 100644
index 0000000..f641892
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/CMUniOp.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd.models;
+
+import org.apache.xerces.impl.dtd.XMLContentSpec;
+
+/**
+ * Content model Uni-Op node.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class CMUniOp extends CMNode
+{
+ // -------------------------------------------------------------------
+ // Constructors
+ // -------------------------------------------------------------------
+ public CMUniOp(int type, CMNode childNode)
+ {
+ super(type);
+
+ // Insure that its one of the types we require
+ if ((type() != XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE)
+ && (type() != XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE)
+ && (type() != XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE))
+ {
+ throw new RuntimeException("ImplementationMessages.VAL_UST");
+ }
+
+ // Store the node and init any data that needs it
+ fChild = childNode;
+ }
+
+
+ // -------------------------------------------------------------------
+ // Package, final methods
+ // -------------------------------------------------------------------
+ final CMNode getChild()
+ {
+ return fChild;
+ }
+
+
+ // -------------------------------------------------------------------
+ // Package, inherited methods
+ // -------------------------------------------------------------------
+ public boolean isNullable()
+ {
+ //
+ // For debugging purposes, make sure we got rid of all non '*'
+ // repetitions. Otherwise, '*' style nodes are always nullable.
+ //
+ if (type() == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE)
+ return fChild.isNullable();
+ else
+ return true;
+ }
+
+
+ // -------------------------------------------------------------------
+ // Protected, inherited methods
+ // -------------------------------------------------------------------
+ protected void calcFirstPos(CMStateSet toSet)
+ {
+ // Its just based on our child node's first pos
+ toSet.setTo(fChild.firstPos());
+ }
+
+ protected void calcLastPos(CMStateSet toSet)
+ {
+ // Its just based on our child node's last pos
+ toSet.setTo(fChild.lastPos());
+ }
+
+
+ // -------------------------------------------------------------------
+ // Private data members
+ //
+ // fChild
+ // This is the reference to the one child that we have for this
+ // unary operation.
+ // -------------------------------------------------------------------
+ private final CMNode fChild;
+};
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/ContentModelValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/ContentModelValidator.java
new file mode 100644
index 0000000..3fa775f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/ContentModelValidator.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd.models;
+
+import org.apache.xerces.xni.QName;
+
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public interface ContentModelValidator {
+
+ //
+ // Methods
+ //
+
+ /**
+ * validate
+ *
+ * @param children
+ * @param offset
+ * @param length
+ *
+ * @return The value -1 if fully valid, else the 0 based index of the child
+ * that first failed. If the value returned is equal to the number
+ * of children, then the specified children are valid but additional
+ * content is required to reach a valid ending state.
+ */
+ public int validate(QName[] children, int offset, int length);
+
+} // interface ContentModelValidator
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/DFAContentModel.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/DFAContentModel.java
new file mode 100644
index 0000000..e24af20
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/DFAContentModel.java
@@ -0,0 +1,987 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd.models;
+
+import java.util.HashMap;
+
+import org.apache.xerces.impl.dtd.XMLContentSpec;
+import org.apache.xerces.xni.QName;
+
+/**
+ * DFAContentModel is the derivative of ContentModel that does
+ * all of the non-trivial element content validation. This class does
+ * the conversion from the regular expression to the DFA that
+ * it then uses in its validation algorithm.
+ *
+ * Note: Upstream work insures that this class will never see
+ * a content model with PCDATA in it. Any model with PCDATA is 'mixed'
+ * and is handled via the MixedContentModel class since mixed models
+ * are very constrained in form and easily handled via a special case.
+ * This also makes implementation of this class much easier.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class DFAContentModel
+ implements ContentModelValidator {
+
+ //
+ // Constants
+ //
+ // special strings
+
+ /** Epsilon string. */
+ private static String fEpsilonString = "<>";
+
+ /** End-of-content string. */
+ private static String fEOCString = "<>";
+
+ /** initializing static members **/
+ static {
+ fEpsilonString = fEpsilonString.intern();
+ fEOCString = fEOCString.intern();
+ }
+
+ // debugging
+
+ /** Set to true to debug content model validation. */
+ private static final boolean DEBUG_VALIDATE_CONTENT = false;
+
+ //
+ // Data
+ //
+
+ /* this is the EquivClassComparator object */
+ //private EquivClassComparator comparator = null;
+
+ /**
+ * This is the map of unique input symbol elements to indices into
+ * each state's per-input symbol transition table entry. This is part
+ * of the built DFA information that must be kept around to do the
+ * actual validation.
+ */
+ private QName fElemMap[] = null;
+
+ /**
+ * This is a map of whether the element map contains information
+ * related to ANY models.
+ */
+ private int fElemMapType[] = null;
+
+ /** The element map size. */
+ private int fElemMapSize = 0;
+
+ /** Boolean to distinguish Schema Mixed Content */
+ private boolean fMixed;
+
+ /**
+ * The NFA position of the special EOC (end of content) node. This
+ * is saved away since it's used during the DFA build.
+ */
+ private int fEOCPos = 0;
+
+
+ /**
+ * This is an array of booleans, one per state (there are
+ * fTransTableSize states in the DFA) that indicates whether that
+ * state is a final state.
+ */
+ private boolean fFinalStateFlags[] = null;
+
+ /**
+ * The list of follow positions for each NFA position (i.e. for each
+ * non-epsilon leaf node.) This is only used during the building of
+ * the DFA, and is let go afterwards.
+ */
+ private CMStateSet fFollowList[] = null;
+
+ /**
+ * This is the head node of our intermediate representation. It is
+ * only non-null during the building of the DFA (just so that it
+ * does not have to be passed all around.) Once the DFA is built,
+ * this is no longer required so its nulled out.
+ */
+ private CMNode fHeadNode = null;
+
+ /**
+ * The count of leaf nodes. This is an important number that set some
+ * limits on the sizes of data structures in the DFA process.
+ */
+ private int fLeafCount = 0;
+
+ /**
+ * An array of non-epsilon leaf nodes, which is used during the DFA
+ * build operation, then dropped.
+ */
+ private CMLeaf fLeafList[] = null;
+
+ /** Array mapping ANY types to the leaf list. */
+ private int fLeafListType[] = null;
+
+ //private ContentLeafNameTypeVector fLeafNameTypeVector = null;
+
+ /**
+ * The string pool of our parser session. This is set during construction
+ * and kept around.
+ */
+ //private StringPool fStringPool = null;
+
+ /**
+ * This is the transition table that is the main by product of all
+ * of the effort here. It is an array of arrays of ints. The first
+ * dimension is the number of states we end up with in the DFA. The
+ * second dimensions is the number of unique elements in the content
+ * model (fElemMapSize). Each entry in the second dimension indicates
+ * the new state given that input for the first dimension's start
+ * state.
+ *
+ * The fElemMap array handles mapping from element indexes to
+ * positions in the second dimension of the transition table.
+ */
+ private int fTransTable[][] = null;
+
+ /**
+ * The number of valid entries in the transition table, and in the other
+ * related tables such as fFinalStateFlags.
+ */
+ private int fTransTableSize = 0;
+
+ /**
+ * Flag that indicates that even though we have a "complicated"
+ * content model, it is valid to have no content. In other words,
+ * all parts of the content model are optional. For example:
+ *
+ * <!ELEMENT AllOptional (Optional*,NotRequired?)>
+ *
+ */
+ private boolean fEmptyContentIsValid = false;
+
+ // temp variables
+
+ /** Temporary qualified name. */
+ private final QName fQName = new QName();
+
+ //
+ // Constructors
+ //
+
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Constructs a DFA content model.
+ *
+ * @param syntaxTree The syntax tree of the content model.
+ * @param leafCount The number of leaves.
+ * @param mixed
+ *
+ */
+ public DFAContentModel(CMNode syntaxTree, int leafCount, boolean mixed) {
+ // Store away our index and pools in members
+ //fStringPool = stringPool;
+ fLeafCount = leafCount;
+
+
+ // this is for Schema Mixed Content
+ fMixed = mixed;
+
+ //
+ // Ok, so lets grind through the building of the DFA. This method
+ // handles the high level logic of the algorithm, but it uses a
+ // number of helper classes to do its thing.
+ //
+ // In order to avoid having hundreds of references to the error and
+ // string handlers around, this guy and all of his helper classes
+ // just throw a simple exception and we then pass it along.
+ //
+ buildDFA(syntaxTree);
+ }
+
+ //
+ // ContentModelValidator methods
+ //
+
+ /**
+ * Check that the specified content is valid according to this
+ * content model. This method can also be called to do 'what if'
+ * testing of content models just to see if they would be valid.
+ *
+ * A value of -1 in the children array indicates a PCDATA node. All other
+ * indexes will be positive and represent child elements. The count can be
+ * zero, since some elements have the EMPTY content model and that must be
+ * confirmed.
+ *
+ * @param children The children of this element. Each integer is an index within
+ * the StringPool of the child element name. An index
+ * of -1 is used to indicate an occurrence of non-whitespace character
+ * data.
+ * @param offset Offset into the array where the children starts.
+ * @param length The number of entries in the children array.
+ *
+ * @return The value -1 if fully valid, else the 0 based index of the child
+ * that first failed. If the value returned is equal to the number
+ * of children, then the specified children are valid but additional
+ * content is required to reach a valid ending state.
+ *
+ */
+ public int validate(QName[] children, int offset, int length) {
+
+ if (DEBUG_VALIDATE_CONTENT)
+ System.out.println("DFAContentModel#validateContent");
+
+ //
+ // A DFA content model must *always* have at least 1 child
+ // so a failure is given if no children present.
+ //
+ // Defect 782: This is an incorrect statement because a DFA
+ // content model is also used for constructions such as:
+ //
+ // (Optional*,NotRequired?)
+ //
+ // where a perfectly valid content would be NO CHILDREN.
+ // Therefore, if there are no children, we must check to
+ // see if the CMNODE_EOC marker is a valid start state! -Ac
+ //
+ if (length == 0) {
+ if (DEBUG_VALIDATE_CONTENT) {
+ System.out.println("!!! no children");
+ System.out.println("elemMap="+fElemMap);
+ for (int i = 0; i < fElemMap.length; i++) {
+ String uri = fElemMap[i].uri;
+ String localpart = fElemMap[i].localpart;
+
+ System.out.println("fElemMap["+i+"]="+uri+","+
+ localpart+" ("+
+ uri+", "+
+ localpart+
+ ')');
+
+ }
+ System.out.println("EOCIndex="+fEOCString);
+ }
+
+ return fEmptyContentIsValid ? -1 : 0;
+
+ } // if child count == 0
+
+ //
+ // Lets loop through the children in the array and move our way
+ // through the states. Note that we use the fElemMap array to map
+ // an element index to a state index.
+ //
+ int curState = 0;
+ for (int childIndex = 0; childIndex < length; childIndex++)
+ {
+ // Get the current element index out
+ final QName curElem = children[offset + childIndex];
+ // ignore mixed text
+ if (fMixed && curElem.localpart == null) {
+ continue;
+ }
+
+ // Look up this child in our element map
+ int elemIndex = 0;
+ for (; elemIndex < fElemMapSize; elemIndex++)
+ {
+ int type = fElemMapType[elemIndex] & 0x0f ;
+ if (type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
+ //System.out.println("fElemMap["+elemIndex+"]: "+fElemMap[elemIndex]);
+ if (fElemMap[elemIndex].rawname == curElem.rawname) {
+ break;
+ }
+ }
+ else if (type == XMLContentSpec.CONTENTSPECNODE_ANY) {
+ String uri = fElemMap[elemIndex].uri;
+ if (uri == null || uri == curElem.uri) {
+ break;
+ }
+ }
+ else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
+ if (curElem.uri == null) {
+ break;
+ }
+ }
+ else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
+ if (fElemMap[elemIndex].uri != curElem.uri) {
+ break;
+ }
+ }
+ }
+
+ // If we didn't find it, then obviously not valid
+ if (elemIndex == fElemMapSize) {
+ if (DEBUG_VALIDATE_CONTENT) {
+ System.out.println("!!! didn't find it");
+
+ System.out.println("curElem : " +curElem );
+ for (int i=0; i
+ * <!ELEMENT Foo ((#PCDATA|a|b|c|)*)>
+ *
+ * So, all we have to do is to keep an array of the possible children and
+ * validate by just looking up each child being validated by looking it up
+ * in the list.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class MixedContentModel
+ implements ContentModelValidator {
+
+ //
+ // Data
+ //
+
+ /** The count of possible children that we have to deal with. */
+ private final int fCount;
+
+ /** The list of possible children that we have to accept. */
+ private final QName fChildren[];
+
+ /** The type of the children to support ANY. */
+ private final int fChildrenType[];
+
+ /* this is the EquivClassComparator object */
+ //private EquivClassComparator comparator = null;
+
+ /**
+ * True if mixed content model is ordered. DTD mixed content models
+ * are always unordered.
+ */
+ private final boolean fOrdered;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Constructs a mixed content model.
+ *
+ * @param children The list of allowed children.
+ * @param type The list of the types of the children.
+ * @param offset The start offset position in the children.
+ * @param length The child count.
+ * @param ordered True if content must be ordered.
+ */
+ public MixedContentModel(QName[] children, int[] type, int offset, int length , boolean ordered) {
+ // Make our own copy now, which is exactly the right size
+ fCount = length;
+ fChildren = new QName[fCount];
+ fChildrenType = new int[fCount];
+ for (int i = 0; i < fCount; i++) {
+ fChildren[i] = new QName(children[offset + i]);
+ fChildrenType[i] = type[offset + i];
+ }
+ fOrdered = ordered;
+
+ }
+
+ //
+ // ContentModelValidator methods
+ //
+
+
+ /**
+ * Check that the specified content is valid according to this
+ * content model. This method can also be called to do 'what if'
+ * testing of content models just to see if they would be valid.
+ *
+ * A value of -1 in the children array indicates a PCDATA node. All other
+ * indexes will be positive and represent child elements. The count can be
+ * zero, since some elements have the EMPTY content model and that must be
+ * confirmed.
+ *
+ * @param children The children of this element. Each integer is an index within
+ * the StringPool of the child element name. An index
+ * of -1 is used to indicate an occurrence of non-whitespace character
+ * data.
+ * @param offset Offset into the array where the children starts.
+ * @param length The number of entries in the children array.
+ *
+ * @return The value -1 if fully valid, else the 0 based index of the child
+ * that first failed. If the value returned is equal to the number
+ * of children, then the specified children are valid but additional
+ * content is required to reach a valid ending state.
+ *
+ */
+ public int validate(QName[] children, int offset, int length) {
+
+ // must match order
+ if (fOrdered) {
+ int inIndex = 0;
+ for (int outIndex = 0; outIndex < length; outIndex++) {
+
+ // ignore mixed text
+ final QName curChild = children[offset + outIndex];
+ if (curChild.localpart == null) {
+ continue;
+ }
+
+ // element must match
+ int type = fChildrenType[inIndex];
+ if (type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
+ if (fChildren[inIndex].rawname != children[offset + outIndex].rawname) {
+ return outIndex;
+ }
+ }
+ else if (type == XMLContentSpec.CONTENTSPECNODE_ANY) {
+ String uri = fChildren[inIndex].uri;
+ if (uri != null && uri != children[outIndex].uri) {
+ return outIndex;
+ }
+ }
+ else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
+ if (children[outIndex].uri != null) {
+ return outIndex;
+ }
+ }
+ else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
+ if (fChildren[inIndex].uri == children[outIndex].uri) {
+ return outIndex;
+ }
+ }
+
+ // advance index
+ inIndex++;
+ }
+ }
+
+ // can appear in any order
+ else {
+ for (int outIndex = 0; outIndex < length; outIndex++)
+ {
+ // Get the current child out of the source index
+ final QName curChild = children[offset + outIndex];
+
+ // If its PCDATA, then we just accept that
+ if (curChild.localpart == null)
+ continue;
+
+ // And try to find it in our list
+ int inIndex = 0;
+ for (; inIndex < fCount; inIndex++)
+ {
+ int type = fChildrenType[inIndex];
+ if (type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
+ if (curChild.rawname == fChildren[inIndex].rawname) {
+ break;
+ }
+ }
+ else if (type == XMLContentSpec.CONTENTSPECNODE_ANY) {
+ String uri = fChildren[inIndex].uri;
+ if (uri == null || uri == children[outIndex].uri) {
+ break;
+ }
+ }
+ else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
+ if (children[outIndex].uri == null) {
+ break;
+ }
+ }
+ else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
+ if (fChildren[inIndex].uri != children[outIndex].uri) {
+ break;
+ }
+ }
+ // REVISIT: What about checking for multiple ANY matches?
+ // The content model ambiguity *could* be checked
+ // by the caller before constructing the mixed
+ // content model.
+ }
+
+ // We did not find this one, so the validation failed
+ if (inIndex == fCount)
+ return outIndex;
+ }
+ }
+
+ // Everything seems to be in order, so return success
+ return -1;
+ } // validate
+
+} // class MixedContentModel
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/SimpleContentModel.java b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/SimpleContentModel.java
new file mode 100644
index 0000000..51d60af
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dtd/models/SimpleContentModel.java
@@ -0,0 +1,276 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dtd.models;
+
+import org.apache.xerces.impl.dtd.XMLContentSpec;
+import org.apache.xerces.xni.QName;
+
+/**
+ * SimpleContentModel is a derivative of the abstract content model base
+ * class that handles a small set of simple content models that are just
+ * way overkill to give the DFA treatment.
+ *
+ * This class handles the following scenarios:
+ *
+ * - a
+ *
- a?
+ *
- a*
+ *
- a+
+ *
- a,b
+ *
- a|b
+ *
+ *
+ * These all involve a unary operation with one element type, or a binary
+ * operation with two elements. These are very simple and can be checked
+ * in a simple way without a DFA and without the overhead of setting up a
+ * DFA for such a simple check.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class SimpleContentModel
+ implements ContentModelValidator {
+
+ //
+ // Constants
+ //
+
+ /** CHOICE */
+ public static final short CHOICE = -1;
+
+ /** SEQUENCE */
+ public static final short SEQUENCE = -1;
+
+ //
+ // Data
+ //
+
+
+ /**
+ * The element decl pool indices of the first (and optional second)
+ * child node. The operation code tells us whether the second child
+ * is used or not.
+ */
+ private final QName fFirstChild = new QName();
+
+ /**
+ * The element decl pool indices of the first (and optional second)
+ * child node. The operation code tells us whether the second child
+ * is used or not.
+ */
+ private final QName fSecondChild = new QName();
+
+ /**
+ * The operation that this object represents. Since this class only
+ * does simple contents, there is only ever a single operation
+ * involved (i.e. the children of the operation are always one or
+ * two leafs.) This is one of the XMLDTDParams.CONTENTSPECNODE_XXX values.
+ */
+ private final int fOperator;
+
+ /* this is the EquivClassComparator object */
+ //private EquivClassComparator comparator = null;
+
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Constructs a simple content model.
+ *
+ * @param operator The content model operator.
+ * @param firstChild qualified name of the first child
+ * @param secondChild qualified name of the second child
+ *
+ */
+ public SimpleContentModel(short operator, QName firstChild, QName secondChild) {
+ //
+ // Store away the children and operation. This is all we need to
+ // do the content model check.
+ //
+ // The operation is one of the ContentSpecNode.NODE_XXX values!
+ //
+ fFirstChild.setValues(firstChild);
+ if (secondChild != null) {
+ fSecondChild.setValues(secondChild);
+ }
+ else {
+ fSecondChild.clear();
+ }
+ fOperator = operator;
+ }
+
+ //
+ // ContentModelValidator methods
+ //
+
+ /**
+ * Check that the specified content is valid according to this
+ * content model. This method can also be called to do 'what if'
+ * testing of content models just to see if they would be valid.
+ *
+ * A value of -1 in the children array indicates a PCDATA node. All other
+ * indexes will be positive and represent child elements. The count can be
+ * zero, since some elements have the EMPTY content model and that must be
+ * confirmed.
+ *
+ * @param children The children of this element. Each integer is an index within
+ * the StringPool of the child element name. An index
+ * of -1 is used to indicate an occurrence of non-whitespace character
+ * data.
+ * @param offset Offset into the array where the children starts.
+ * @param length The number of entries in the children array.
+ *
+ * @return The value -1 if fully valid, else the 0 based index of the child
+ * that first failed. If the value returned is equal to the number
+ * of children, then the specified children are valid but additional
+ * content is required to reach a valid ending state.
+ *
+ */
+ public int validate(QName[] children, int offset, int length) {
+
+ //
+ // According to the type of operation, we do the correct type of
+ // content check.
+ //
+ switch(fOperator)
+ {
+ case XMLContentSpec.CONTENTSPECNODE_LEAF :
+ // If there is not a child, then report an error at index 0
+ if (length == 0)
+ return 0;
+
+ // If the 0th child is not the right kind, report an error at 0
+ if (children[offset].rawname != fFirstChild.rawname) {
+ return 0;
+ }
+
+ // If more than one child, report an error at index 1
+ if (length > 1)
+ return 1;
+ break;
+
+ case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE :
+ //
+ // If there is one child, make sure its the right type. If not,
+ // then its an error at index 0.
+ //
+ if (length == 1) {
+ if (children[offset].rawname != fFirstChild.rawname) {
+ return 0;
+ }
+ }
+
+ //
+ // If the child count is greater than one, then obviously
+ // bad, so report an error at index 1.
+ //
+ if (length > 1)
+ return 1;
+ break;
+
+ case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE :
+ //
+ // If the child count is zero, that's fine. If its more than
+ // zero, then make sure that all children are of the element
+ // type that we stored. If not, report the index of the first
+ // failed one.
+ //
+ if (length > 0)
+ {
+ for (int index = 0; index < length; index++) {
+ if (children[offset + index].rawname != fFirstChild.rawname) {
+ return index;
+ }
+ }
+ }
+ break;
+
+ case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE :
+ //
+ // If the child count is zero, that's an error so report
+ // an error at index 0.
+ //
+ if (length == 0)
+ return 0;
+
+ //
+ // Otherwise we have to check them all to make sure that they
+ // are of the correct child type. If not, then report the index
+ // of the first one that is not.
+ //
+ for (int index = 0; index < length; index++) {
+ if (children[offset + index].rawname != fFirstChild.rawname) {
+ return index;
+ }
+ }
+ break;
+
+ case XMLContentSpec.CONTENTSPECNODE_CHOICE :
+ //
+ // There must be one and only one child, so if the element count
+ // is zero, return an error at index 0.
+ //
+ if (length == 0)
+ return 0;
+
+ // If the zeroth element isn't one of our choices, error at 0
+ if ((children[offset].rawname != fFirstChild.rawname) &&
+ (children[offset].rawname != fSecondChild.rawname)) {
+ return 0;
+ }
+
+ // If there is more than one element, then an error at 1
+ if (length > 1)
+ return 1;
+ break;
+
+ case XMLContentSpec.CONTENTSPECNODE_SEQ :
+ //
+ // There must be two children and they must be the two values
+ // we stored, in the stored order.
+ //
+ if (length == 2) {
+ if (children[offset].rawname != fFirstChild.rawname) {
+ return 0;
+ }
+ if (children[offset + 1].rawname != fSecondChild.rawname) {
+ return 1;
+ }
+ }
+ else {
+ if (length > 2) {
+ return 2;
+ }
+
+ return length;
+ }
+
+ break;
+
+ default :
+ throw new RuntimeException("ImplementationMessages.VAL_CST");
+ }
+
+ // We survived, so return success status
+ return -1;
+ } // validate
+
+} // class SimpleContentModel
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/DTDDVFactory.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/DTDDVFactory.java
new file mode 100644
index 0000000..35e7eee
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/DTDDVFactory.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+import java.util.Hashtable;
+
+/**
+ * The factory to create and return DTD types. The implementation should
+ * store the created datatypes in static data, so that they can be shared by
+ * multiple parser instance, and multiple threads.
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public abstract class DTDDVFactory {
+
+ private static final String DEFAULT_FACTORY_CLASS = "org.apache.xerces.impl.dv.dtd.DTDDVFactoryImpl";
+
+ /**
+ * Get an instance of the default DTDDVFactory implementation.
+ *
+ * @return an instance of DTDDVFactory implementation
+ * @exception DVFactoryException cannot create an instance of the specified
+ * class name or the default class name
+ */
+ public static final DTDDVFactory getInstance() throws DVFactoryException {
+ return getInstance(DEFAULT_FACTORY_CLASS);
+ }
+
+ /**
+ * Get an instance of DTDDVFactory implementation.
+ *
+ * @param factoryClass name of the implementation to load.
+ * @return an instance of DTDDVFactory implementation
+ * @exception DVFactoryException cannot create an instance of the specified
+ * class name or the default class name
+ */
+ public static final DTDDVFactory getInstance(String factoryClass) throws DVFactoryException {
+ try {
+ // if the class name is not specified, use the default one
+ return (DTDDVFactory)
+ (ObjectFactory.newInstance(factoryClass, ObjectFactory.findClassLoader(), true));
+ }
+ catch (ClassCastException e) {
+ throw new DVFactoryException("DTD factory class " + factoryClass + " does not extend from DTDDVFactory.");
+ }
+ }
+
+ // can't create a new object of this class
+ protected DTDDVFactory() {}
+
+ /**
+ * return a dtd type of the given name
+ *
+ * @param name the name of the datatype
+ * @return the datatype validator of the given name
+ */
+ public abstract DatatypeValidator getBuiltInDV(String name);
+
+ /**
+ * get all built-in DVs, which are stored in a hashtable keyed by the name
+ *
+ * @return a hashtable which contains all datatypes
+ */
+ public abstract Hashtable getBuiltInTypes();
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/DVFactoryException.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/DVFactoryException.java
new file mode 100644
index 0000000..7a7b879
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/DVFactoryException.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+/**
+ * A runtime exception that's thrown if an error happens when the application
+ * tries to get a DV factory instance.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class DVFactoryException extends RuntimeException {
+
+ /** Serialization version. */
+ static final long serialVersionUID = -3738854697928682412L;
+
+ public DVFactoryException() {
+ super();
+ }
+
+ public DVFactoryException(String msg) {
+ super(msg);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/DatatypeException.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/DatatypeException.java
new file mode 100644
index 0000000..ca06e63
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/DatatypeException.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Base class for datatype exceptions. For DTD types, the exception can be
+ * created from an error message. For Schema types, it needs an error code
+ * (as defined in Appendix C of the structure spec), plus an array of arguments,
+ * for error message substitution.
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class DatatypeException extends Exception {
+
+ /** Serialization version. */
+ static final long serialVersionUID = 1940805832730465578L;
+
+ // used to store error code and error substitution arguments
+ protected final String key;
+ protected final Object[] args;
+
+ /**
+ * Create a new datatype exception by providing an error code and a list
+ * of error message substitution arguments.
+ *
+ * @param key error code
+ * @param args error arguments
+ */
+ public DatatypeException(String key, Object[] args) {
+ super(key);
+ this.key = key;
+ this.args = args;
+ }
+
+ /**
+ * Return the error code
+ *
+ * @return error code
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * Return the list of error arguments
+ *
+ * @return error arguments
+ */
+ public Object[] getArgs() {
+ return args;
+ }
+
+ /**
+ * Overrides this method to get the formatted&localized error message.
+ *
+ * REVISIT: the system locale is used to load the property file.
+ * do we want to allow the appilcation to specify a
+ * different locale?
+ */
+ public String getMessage() {
+ ResourceBundle resourceBundle = null;
+ resourceBundle = ResourceBundle.getBundle("org.apache.xerces.impl.msg.XMLSchemaMessages");
+ if (resourceBundle == null)
+ throw new MissingResourceException("Property file not found!", "org.apache.xerces.impl.msg.XMLSchemaMessages", key);
+
+ String msg = resourceBundle.getString(key);
+ if (msg == null) {
+ msg = resourceBundle.getString("BadMessageKey");
+ throw new MissingResourceException(msg, "org.apache.xerces.impl.msg.XMLSchemaMessages", key);
+ }
+
+ if (args != null) {
+ try {
+ msg = java.text.MessageFormat.format(msg, args);
+ } catch (Exception e) {
+ msg = resourceBundle.getString("FormatFailed");
+ msg += " " + resourceBundle.getString(key);
+ }
+ }
+
+ return msg;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/DatatypeValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/DatatypeValidator.java
new file mode 100644
index 0000000..2357e11
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/DatatypeValidator.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+
+/**
+ * The interface that a DTD datatype must implement. The implementation of this
+ * interface must be thread-safe.
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public interface DatatypeValidator {
+
+ /**
+ * validate a given string against this DV
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ */
+ public void validate(String content, ValidationContext context)
+ throws InvalidDatatypeValueException;
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/InvalidDatatypeFacetException.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/InvalidDatatypeFacetException.java
new file mode 100644
index 0000000..8e8ea5a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/InvalidDatatypeFacetException.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+/**
+ * Datatype exception for invalid facet. This exception is only used by
+ * schema datatypes.
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class InvalidDatatypeFacetException extends DatatypeException {
+
+ /** Serialization version. */
+ static final long serialVersionUID = -4104066085909970654L;
+
+ /**
+ * Create a new datatype exception by providing an error code and a list
+ * of error message substitution arguments.
+ *
+ * @param key error code
+ * @param args error arguments
+ */
+ public InvalidDatatypeFacetException(String key, Object[] args) {
+ super(key, args);
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/InvalidDatatypeValueException.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/InvalidDatatypeValueException.java
new file mode 100644
index 0000000..65672f0
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/InvalidDatatypeValueException.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+/**
+ * Datatype exception for invalid values.
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class InvalidDatatypeValueException extends DatatypeException {
+
+ /** Serialization version. */
+ static final long serialVersionUID = -5523739426958236125L;
+
+ /**
+ * Create a new datatype exception by providing an error code and a list
+ * of error message substitution arguments.
+ *
+ * @param key error code
+ * @param args error arguments
+ */
+ public InvalidDatatypeValueException(String key, Object[] args) {
+ super(key, args);
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/ObjectFactory.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/ObjectFactory.java
new file mode 100644
index 0000000..07a6aed
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/ObjectFactory.java
@@ -0,0 +1,545 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Properties;
+
+/**
+ * This class is duplicated for each JAXP subpackage so keep it in sync.
+ * It is package private and therefore is not exposed as part of the JAXP
+ * API.
+ *
+ * This code is designed to implement the JAXP 1.1 spec pluggability
+ * feature and is designed to run on JDK version 1.1 and
+ * later, and to compile on JDK 1.2 and onward.
+ * The code also runs both as part of an unbundled jar file and
+ * when bundled as part of the JDK.
+ *
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+final class ObjectFactory {
+
+ //
+ // Constants
+ //
+
+ // name of default properties file to look for in JDK's jre/lib directory
+ private static final String DEFAULT_PROPERTIES_FILENAME = "xerces.properties";
+
+ /** Set to true for debugging */
+ private static final boolean DEBUG = isDebugEnabled();
+
+ /**
+ * Default columns per line.
+ */
+ private static final int DEFAULT_LINE_LENGTH = 80;
+
+ /** cache the contents of the xerces.properties file.
+ * Until an attempt has been made to read this file, this will
+ * be null; if the file does not exist or we encounter some other error
+ * during the read, this will be empty.
+ */
+ private static Properties fXercesProperties = null;
+
+ /***
+ * Cache the time stamp of the xerces.properties file so
+ * that we know if it's been modified and can invalidate
+ * the cache when necessary.
+ */
+ private static long fLastModified = -1;
+
+ //
+ // static methods
+ //
+
+ /**
+ * Finds the implementation Class object in the specified order. The
+ * specified order is the following:
+ *
+ * - query the system property using
System.getProperty
+ * - read
META-INF/services/factoryId file
+ * - use fallback classname
+ *
+ *
+ * @return Class object of factory, never null
+ *
+ * @param factoryId Name of the factory to find, same as
+ * a property name
+ * @param fallbackClassName Implementation class name, if nothing else
+ * is found. Use null to mean no fallback.
+ *
+ * @exception ObjectFactory.ConfigurationError
+ */
+ static Object createObject(String factoryId, String fallbackClassName)
+ throws ConfigurationError {
+ return createObject(factoryId, null, fallbackClassName);
+ } // createObject(String,String):Object
+
+ /**
+ * Finds the implementation Class object in the specified order. The
+ * specified order is the following:
+ *
+ * - query the system property using
System.getProperty
+ * - read
$java.home/lib/propertiesFilename file
+ * - read
META-INF/services/factoryId file
+ * - use fallback classname
+ *
+ *
+ * @return Class object of factory, never null
+ *
+ * @param factoryId Name of the factory to find, same as
+ * a property name
+ * @param propertiesFilename The filename in the $java.home/lib directory
+ * of the properties file. If none specified,
+ * ${java.home}/lib/xerces.properties will be used.
+ * @param fallbackClassName Implementation class name, if nothing else
+ * is found. Use null to mean no fallback.
+ *
+ * @exception ObjectFactory.ConfigurationError
+ */
+ static Object createObject(String factoryId,
+ String propertiesFilename,
+ String fallbackClassName)
+ throws ConfigurationError
+ {
+ if (DEBUG) debugPrintln("debug is on");
+
+ ClassLoader cl = findClassLoader();
+
+ // Use the system property first
+ try {
+ String systemProp = SecuritySupport.getSystemProperty(factoryId);
+ if (systemProp != null && systemProp.length() > 0) {
+ if (DEBUG) debugPrintln("found system property, value=" + systemProp);
+ return newInstance(systemProp, cl, true);
+ }
+ } catch (SecurityException se) {
+ // Ignore and continue w/ next location
+ }
+
+ // Try to read from propertiesFilename, or $java.home/lib/xerces.properties
+ String factoryClassName = null;
+ // no properties file name specified; use $JAVA_HOME/lib/xerces.properties:
+ if (propertiesFilename == null) {
+ File propertiesFile = null;
+ boolean propertiesFileExists = false;
+ try {
+ String javah = SecuritySupport.getSystemProperty("java.home");
+ propertiesFilename = javah + File.separator +
+ "lib" + File.separator + DEFAULT_PROPERTIES_FILENAME;
+ propertiesFile = new File(propertiesFilename);
+ propertiesFileExists = SecuritySupport.getFileExists(propertiesFile);
+ } catch (SecurityException e) {
+ // try again...
+ fLastModified = -1;
+ fXercesProperties = null;
+ }
+
+ synchronized (ObjectFactory.class) {
+ boolean loadProperties = false;
+ FileInputStream fis = null;
+ try {
+ // file existed last time
+ if(fLastModified >= 0) {
+ if(propertiesFileExists &&
+ (fLastModified < (fLastModified = SecuritySupport.getLastModified(propertiesFile)))) {
+ loadProperties = true;
+ } else {
+ // file has stopped existing...
+ if(!propertiesFileExists) {
+ fLastModified = -1;
+ fXercesProperties = null;
+ } // else, file wasn't modified!
+ }
+ } else {
+ // file has started to exist:
+ if(propertiesFileExists) {
+ loadProperties = true;
+ fLastModified = SecuritySupport.getLastModified(propertiesFile);
+ } // else, nothing's changed
+ }
+ if(loadProperties) {
+ // must never have attempted to read xerces.properties before (or it's outdeated)
+ fXercesProperties = new Properties();
+ fis = SecuritySupport.getFileInputStream(propertiesFile);
+ fXercesProperties.load(fis);
+ }
+ } catch (Exception x) {
+ fXercesProperties = null;
+ fLastModified = -1;
+ // assert(x instanceof FileNotFoundException
+ // || x instanceof SecurityException)
+ // In both cases, ignore and continue w/ next location
+ }
+ finally {
+ // try to close the input stream if one was opened.
+ if (fis != null) {
+ try {
+ fis.close();
+ }
+ // Ignore the exception.
+ catch (IOException exc) {}
+ }
+ }
+ }
+ if(fXercesProperties != null) {
+ factoryClassName = fXercesProperties.getProperty(factoryId);
+ }
+ } else {
+ FileInputStream fis = null;
+ try {
+ fis = SecuritySupport.getFileInputStream(new File(propertiesFilename));
+ Properties props = new Properties();
+ props.load(fis);
+ factoryClassName = props.getProperty(factoryId);
+ } catch (Exception x) {
+ // assert(x instanceof FileNotFoundException
+ // || x instanceof SecurityException)
+ // In both cases, ignore and continue w/ next location
+ }
+ finally {
+ // try to close the input stream if one was opened.
+ if (fis != null) {
+ try {
+ fis.close();
+ }
+ // Ignore the exception.
+ catch (IOException exc) {}
+ }
+ }
+ }
+ if (factoryClassName != null) {
+ if (DEBUG) debugPrintln("found in " + propertiesFilename + ", value=" + factoryClassName);
+ return newInstance(factoryClassName, cl, true);
+ }
+
+ // Try Jar Service Provider Mechanism
+ Object provider = findJarServiceProvider(factoryId);
+ if (provider != null) {
+ return provider;
+ }
+
+ if (fallbackClassName == null) {
+ throw new ConfigurationError(
+ "Provider for " + factoryId + " cannot be found", null);
+ }
+
+ if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName);
+ return newInstance(fallbackClassName, cl, true);
+ } // createObject(String,String,String):Object
+
+ //
+ // Private static methods
+ //
+
+ /** Returns true if debug has been enabled. */
+ private static boolean isDebugEnabled() {
+ try {
+ String val = SecuritySupport.getSystemProperty("xerces.debug");
+ // Allow simply setting the prop to turn on debug
+ return (val != null && (!"false".equals(val)));
+ }
+ catch (SecurityException se) {}
+ return false;
+ } // isDebugEnabled()
+
+ /** Prints a message to standard error if debugging is enabled. */
+ private static void debugPrintln(String msg) {
+ if (DEBUG) {
+ System.err.println("XERCES: " + msg);
+ }
+ } // debugPrintln(String)
+
+ /**
+ * Figure out which ClassLoader to use. For JDK 1.2 and later use
+ * the context ClassLoader.
+ */
+ static ClassLoader findClassLoader()
+ throws ConfigurationError
+ {
+ // Figure out which ClassLoader to use for loading the provider
+ // class. If there is a Context ClassLoader then use it.
+ ClassLoader context = SecuritySupport.getContextClassLoader();
+ ClassLoader system = SecuritySupport.getSystemClassLoader();
+
+ ClassLoader chain = system;
+ while (true) {
+ if (context == chain) {
+ // Assert: we are on JDK 1.1 or we have no Context ClassLoader
+ // or any Context ClassLoader in chain of system classloader
+ // (including extension ClassLoader) so extend to widest
+ // ClassLoader (always look in system ClassLoader if Xerces
+ // is in boot/extension/system classpath and in current
+ // ClassLoader otherwise); normal classloaders delegate
+ // back to system ClassLoader first so this widening doesn't
+ // change the fact that context ClassLoader will be consulted
+ ClassLoader current = ObjectFactory.class.getClassLoader();
+
+ chain = system;
+ while (true) {
+ if (current == chain) {
+ // Assert: Current ClassLoader in chain of
+ // boot/extension/system ClassLoaders
+ return system;
+ }
+ if (chain == null) {
+ break;
+ }
+ chain = SecuritySupport.getParentClassLoader(chain);
+ }
+
+ // Assert: Current ClassLoader not in chain of
+ // boot/extension/system ClassLoaders
+ return current;
+ }
+
+ if (chain == null) {
+ // boot ClassLoader reached
+ break;
+ }
+
+ // Check for any extension ClassLoaders in chain up to
+ // boot ClassLoader
+ chain = SecuritySupport.getParentClassLoader(chain);
+ };
+
+ // Assert: Context ClassLoader not in chain of
+ // boot/extension/system ClassLoaders
+ return context;
+ } // findClassLoader():ClassLoader
+
+ /**
+ * Create an instance of a class using the specified ClassLoader
+ */
+ static Object newInstance(String className, ClassLoader cl,
+ boolean doFallback)
+ throws ConfigurationError
+ {
+ // assert(className != null);
+ try{
+ Class providerClass = findProviderClass(className, cl, doFallback);
+ Object instance = providerClass.newInstance();
+ if (DEBUG) debugPrintln("created new instance of " + providerClass +
+ " using ClassLoader: " + cl);
+ return instance;
+ } catch (ClassNotFoundException x) {
+ throw new ConfigurationError(
+ "Provider " + className + " not found", x);
+ } catch (Exception x) {
+ throw new ConfigurationError(
+ "Provider " + className + " could not be instantiated: " + x,
+ x);
+ }
+ }
+
+ /**
+ * Find a Class using the specified ClassLoader
+ */
+ static Class findProviderClass(String className, ClassLoader cl,
+ boolean doFallback)
+ throws ClassNotFoundException, ConfigurationError
+ {
+ //throw security exception if the calling thread is not allowed to access the package
+ //restrict the access to package as specified in java.security policy
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ final int lastDot = className.lastIndexOf('.');
+ String packageName = className;
+ if (lastDot != -1) packageName = className.substring(0, lastDot);
+ security.checkPackageAccess(packageName);
+ }
+ Class providerClass;
+ if (cl == null) {
+ // XXX Use the bootstrap ClassLoader. There is no way to
+ // load a class using the bootstrap ClassLoader that works
+ // in both JDK 1.1 and Java 2. However, this should still
+ // work b/c the following should be true:
+ //
+ // (cl == null) iff current ClassLoader == null
+ //
+ // Thus Class.forName(String) will use the current
+ // ClassLoader which will be the bootstrap ClassLoader.
+ providerClass = Class.forName(className);
+ } else {
+ try {
+ providerClass = cl.loadClass(className);
+ } catch (ClassNotFoundException x) {
+ if (doFallback) {
+ // Fall back to current classloader
+ ClassLoader current = ObjectFactory.class.getClassLoader();
+ if (current == null) {
+ providerClass = Class.forName(className);
+ } else if (cl != current) {
+ cl = current;
+ providerClass = cl.loadClass(className);
+ } else {
+ throw x;
+ }
+ } else {
+ throw x;
+ }
+ }
+ }
+
+ return providerClass;
+ }
+
+ /*
+ * Try to find provider using Jar Service Provider Mechanism
+ *
+ * @return instance of provider class if found or null
+ */
+ private static Object findJarServiceProvider(String factoryId)
+ throws ConfigurationError
+ {
+ String serviceId = "META-INF/services/" + factoryId;
+ InputStream is = null;
+
+ // First try the Context ClassLoader
+ ClassLoader cl = findClassLoader();
+
+ is = SecuritySupport.getResourceAsStream(cl, serviceId);
+
+ // If no provider found then try the current ClassLoader
+ if (is == null) {
+ ClassLoader current = ObjectFactory.class.getClassLoader();
+ if (cl != current) {
+ cl = current;
+ is = SecuritySupport.getResourceAsStream(cl, serviceId);
+ }
+ }
+
+ if (is == null) {
+ // No provider found
+ return null;
+ }
+
+ if (DEBUG) debugPrintln("found jar resource=" + serviceId +
+ " using ClassLoader: " + cl);
+
+ // Read the service provider name in UTF-8 as specified in
+ // the jar spec. Unfortunately this fails in Microsoft
+ // VJ++, which does not implement the UTF-8
+ // encoding. Theoretically, we should simply let it fail in
+ // that case, since the JVM is obviously broken if it
+ // doesn't support such a basic standard. But since there
+ // are still some users attempting to use VJ++ for
+ // development, we have dropped in a fallback which makes a
+ // second attempt using the platform's default encoding. In
+ // VJ++ this is apparently ASCII, which is a subset of
+ // UTF-8... and since the strings we'll be reading here are
+ // also primarily limited to the 7-bit ASCII range (at
+ // least, in English versions), this should work well
+ // enough to keep us on the air until we're ready to
+ // officially decommit from VJ++. [Edited comment from
+ // jkesselm]
+ BufferedReader rd;
+ try {
+ rd = new BufferedReader(new InputStreamReader(is, "UTF-8"), DEFAULT_LINE_LENGTH);
+ } catch (java.io.UnsupportedEncodingException e) {
+ rd = new BufferedReader(new InputStreamReader(is), DEFAULT_LINE_LENGTH);
+ }
+
+ String factoryClassName = null;
+ try {
+ // XXX Does not handle all possible input as specified by the
+ // Jar Service Provider specification
+ factoryClassName = rd.readLine();
+ } catch (IOException x) {
+ // No provider found
+ return null;
+ }
+ finally {
+ try {
+ // try to close the reader.
+ rd.close();
+ }
+ // Ignore the exception.
+ catch (IOException exc) {}
+ }
+
+ if (factoryClassName != null &&
+ ! "".equals(factoryClassName)) {
+ if (DEBUG) debugPrintln("found in resource, value="
+ + factoryClassName);
+
+ // Note: here we do not want to fall back to the current
+ // ClassLoader because we want to avoid the case where the
+ // resource file was found using one ClassLoader and the
+ // provider class was instantiated using a different one.
+ return newInstance(factoryClassName, cl, false);
+ }
+
+ // No provider found
+ return null;
+ }
+
+ //
+ // Classes
+ //
+
+ /**
+ * A configuration error.
+ */
+ static final class ConfigurationError
+ extends Error {
+
+ /** Serialization version. */
+ static final long serialVersionUID = 8521878292694272124L;
+
+ //
+ // Data
+ //
+
+ /** Exception. */
+ private Exception exception;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Construct a new instance with the specified detail string and
+ * exception.
+ */
+ ConfigurationError(String msg, Exception x) {
+ super(msg);
+ this.exception = x;
+ } // (String,Exception)
+
+ //
+ // methods
+ //
+
+ /** Returns the exception associated to this error. */
+ Exception getException() {
+ return exception;
+ } // getException():Exception
+
+ } // class ConfigurationError
+
+} // class ObjectFactory
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/SchemaDVFactory.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/SchemaDVFactory.java
new file mode 100644
index 0000000..1f43963
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/SchemaDVFactory.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+import org.apache.xerces.util.SymbolHash;
+import org.apache.xerces.xs.XSObjectList;
+
+/**
+ * Defines a factory API that enables applications to
+ * 1. to get the instance of specified SchemaDVFactory implementation
+ * 2. to create/return built-in schema simple types
+ * 3. to create user defined simple types.
+ *
+ * Implementations of this abstract class can be used to get built-in simple
+ * types and create user-defined simle types.
+ *
+ * The implementation should store the built-in datatypes in static data, so
+ * that they can be shared by multiple parser instance, and multiple threads.
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public abstract class SchemaDVFactory {
+
+ private static final String DEFAULT_FACTORY_CLASS = "org.apache.xerces.impl.dv.xs.SchemaDVFactoryImpl";
+
+ /**
+ * Get a default instance of SchemaDVFactory implementation.
+ *
+ * @return an instance of SchemaDVFactory implementation
+ * @exception DVFactoryException cannot create an instance of the specified
+ * class name or the default class name
+ */
+ public static final SchemaDVFactory getInstance() throws DVFactoryException {
+ return getInstance(DEFAULT_FACTORY_CLASS);
+ } //getInstance(): SchemaDVFactory
+
+
+ /**
+ * Get an instance of SchemaDVFactory implementation.
+ *
+ * @param factoryClass name of the schema factory implementation to instantiate.
+ * @return an instance of SchemaDVFactory implementation
+ * @exception DVFactoryException cannot create an instance of the specified
+ * class name or the default class name
+ */
+ public static final SchemaDVFactory getInstance(String factoryClass) throws DVFactoryException {
+ try {
+ // if the class name is not specified, use the default one
+ return (SchemaDVFactory)(ObjectFactory.newInstance(
+ factoryClass, ObjectFactory.findClassLoader(), true));
+ }
+ catch (ClassCastException e4) {
+ throw new DVFactoryException("Schema factory class " + factoryClass + " does not extend from SchemaDVFactory.");
+ }
+ }
+
+ // can't create a new object of this class
+ protected SchemaDVFactory() {}
+
+ /**
+ * Get a built-in simple type of the given name
+ * REVISIT: its still not decided within the Schema WG how to define the
+ * ur-types and if all simple types should be derived from a
+ * complex type, so as of now we ignore the fact that anySimpleType
+ * is derived from anyType, and pass 'null' as the base of
+ * anySimpleType. It needs to be changed as per the decision taken.
+ *
+ * @param name the name of the datatype
+ * @return the datatype validator of the given name
+ */
+ public abstract XSSimpleType getBuiltInType(String name);
+
+ /**
+ * get all built-in simple types, which are stored in a SymbolHash keyed by
+ * the name
+ *
+ * @return a SymbolHash which contains all built-in simple types
+ */
+ public abstract SymbolHash getBuiltInTypes();
+
+ /**
+ * Create a new simple type which is derived by restriction from another
+ * simple type.
+ *
+ * @param name name of the new type, could be null
+ * @param targetNamespace target namespace of the new type, could be null
+ * @param finalSet value of "final"
+ * @param base base type of the new type
+ * @param annotations set of annotations
+ * @return the newly created simple type
+ */
+ public abstract XSSimpleType createTypeRestriction(String name, String targetNamespace,
+ short finalSet, XSSimpleType base,
+ XSObjectList annotations);
+
+ /**
+ * Create a new simple type which is derived by list from another simple
+ * type.
+ *
+ * @param name name of the new type, could be null
+ * @param targetNamespace target namespace of the new type, could be null
+ * @param finalSet value of "final"
+ * @param itemType item type of the list type
+ * @param annotations set of annotations
+ * @return the newly created simple type
+ */
+ public abstract XSSimpleType createTypeList(String name, String targetNamespace,
+ short finalSet, XSSimpleType itemType,
+ XSObjectList annotations);
+
+ /**
+ * Create a new simple type which is derived by union from a list of other
+ * simple types.
+ *
+ * @param name name of the new type, could be null
+ * @param targetNamespace target namespace of the new type, could be null
+ * @param finalSet value of "final"
+ * @param memberTypes member types of the union type
+ * @param annotations set of annotations
+ * @return the newly created simple type
+ */
+ public abstract XSSimpleType createTypeUnion(String name, String targetNamespace,
+ short finalSet, XSSimpleType[] memberTypes,
+ XSObjectList annotations);
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/SecuritySupport.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/SecuritySupport.java
new file mode 100644
index 0000000..4b98ea7
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/SecuritySupport.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * This class is duplicated for each subpackage so keep it in sync.
+ * It is package private and therefore is not exposed as part of any API.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+final class SecuritySupport {
+
+ static ClassLoader getContextClassLoader() {
+ return (ClassLoader)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ ClassLoader cl = null;
+ try {
+ cl = Thread.currentThread().getContextClassLoader();
+ } catch (SecurityException ex) { }
+ return cl;
+ }
+ });
+ }
+
+ static ClassLoader getSystemClassLoader() {
+ return (ClassLoader)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ ClassLoader cl = null;
+ try {
+ cl = ClassLoader.getSystemClassLoader();
+ } catch (SecurityException ex) {}
+ return cl;
+ }
+ });
+ }
+
+ static ClassLoader getParentClassLoader(final ClassLoader cl) {
+ return (ClassLoader)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ ClassLoader parent = null;
+ try {
+ parent = cl.getParent();
+ } catch (SecurityException ex) {}
+
+ // eliminate loops in case of the boot
+ // ClassLoader returning itself as a parent
+ return (parent == cl) ? null : parent;
+ }
+ });
+ }
+
+ static String getSystemProperty(final String propName) {
+ return (String)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return System.getProperty(propName);
+ }
+ });
+ }
+
+ static FileInputStream getFileInputStream(final File file)
+ throws FileNotFoundException
+ {
+ try {
+ return (FileInputStream)
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws FileNotFoundException {
+ return new FileInputStream(file);
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw (FileNotFoundException)e.getException();
+ }
+ }
+
+ static InputStream getResourceAsStream(final ClassLoader cl,
+ final String name)
+ {
+ return (InputStream)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ InputStream ris;
+ if (cl == null) {
+ ris = ClassLoader.getSystemResourceAsStream(name);
+ } else {
+ ris = cl.getResourceAsStream(name);
+ }
+ return ris;
+ }
+ });
+ }
+
+ static boolean getFileExists(final File f) {
+ return ((Boolean)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return f.exists() ? Boolean.TRUE : Boolean.FALSE;
+ }
+ })).booleanValue();
+ }
+
+ static long getLastModified(final File f) {
+ return ((Long)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return new Long(f.lastModified());
+ }
+ })).longValue();
+ }
+
+ private SecuritySupport () {}
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/ValidatedInfo.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/ValidatedInfo.java
new file mode 100644
index 0000000..4d094ee
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/ValidatedInfo.java
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+import org.apache.xerces.impl.xs.util.ShortListImpl;
+import org.apache.xerces.impl.xs.util.XSObjectListImpl;
+import org.apache.xerces.xs.ShortList;
+import org.apache.xerces.xs.XSConstants;
+import org.apache.xerces.xs.XSObjectList;
+import org.apache.xerces.xs.XSSimpleTypeDefinition;
+import org.apache.xerces.xs.XSValue;
+
+/**
+ * Class to get the information back after content is validated. This info
+ * would be filled by validate().
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ *
+ * @version $Id$
+ */
+public class ValidatedInfo implements XSValue {
+
+ /**
+ * The normalized value of a string value
+ */
+ public String normalizedValue;
+
+ /**
+ * The actual value from a string value (QName, Boolean, etc.)
+ * An array of Objects if the type is a list.
+ */
+ public Object actualValue;
+
+ /**
+ * The type of the actual value. It's one of the _DT constants
+ * defined in XSConstants.java. The value is used to indicate
+ * the most specific built-in type.
+ * (i.e. short instead of decimal or integer).
+ */
+ public short actualValueType;
+
+ /**
+ * The declared type of the value.
+ */
+ public XSSimpleType actualType;
+
+ /**
+ * If the type is a union type, then the member type which
+ * actually validated the string value.
+ */
+ public XSSimpleType memberType;
+
+ /**
+ * If
+ * 1. the type is a union type where one of the member types is a list, or
+ * if the type is a list; and
+ * 2. the item type of the list is a union type
+ * then an array of member types used to validate the values.
+ */
+ public XSSimpleType[] memberTypes;
+
+ /**
+ * In the case the value is a list or a list of unions, this value
+ * indicates the type(s) of the items in the list.
+ * For a normal list, the length of the array is 1; for list of unions,
+ * the length of the array is the same as the length of the list.
+ */
+ public ShortList itemValueTypes;
+
+ /**
+ * reset the state of this object
+ */
+ public void reset() {
+ this.normalizedValue = null;
+ this.actualValue = null;
+ this.actualValueType = XSConstants.UNAVAILABLE_DT;
+ this.actualType = null;
+ this.memberType = null;
+ this.memberTypes = null;
+ this.itemValueTypes = null;
+ }
+
+ /**
+ * Return a string representation of the value. If there is an actual
+ * value, use toString; otherwise, use the normalized value.
+ */
+ public String stringValue() {
+ if (actualValue == null) {
+ return normalizedValue;
+ }
+ else {
+ return actualValue.toString();
+ }
+ }
+
+ /**
+ * Returns true if the two ValidatedInfo objects can be compared in the same
+ * value space.
+ */
+ public static boolean isComparable(ValidatedInfo info1, ValidatedInfo info2) {
+ final short primitiveType1 = convertToPrimitiveKind(info1.actualValueType);
+ final short primitiveType2 = convertToPrimitiveKind(info2.actualValueType);
+ if (primitiveType1 != primitiveType2) {
+ return (primitiveType1 == XSConstants.ANYSIMPLETYPE_DT && primitiveType2 == XSConstants.STRING_DT ||
+ primitiveType1 == XSConstants.STRING_DT && primitiveType2 == XSConstants.ANYSIMPLETYPE_DT);
+ }
+ else if (primitiveType1 == XSConstants.LIST_DT || primitiveType1 == XSConstants.LISTOFUNION_DT) {
+ final ShortList typeList1 = info1.itemValueTypes;
+ final ShortList typeList2 = info2.itemValueTypes;
+ final int typeList1Length = typeList1 != null ? typeList1.getLength() : 0;
+ final int typeList2Length = typeList2 != null ? typeList2.getLength() : 0;
+ if (typeList1Length != typeList2Length) {
+ return false;
+ }
+ for (int i = 0; i < typeList1Length; ++i) {
+ final short primitiveItem1 = convertToPrimitiveKind(typeList1.item(i));
+ final short primitiveItem2 = convertToPrimitiveKind(typeList2.item(i));
+ if (primitiveItem1 != primitiveItem2) {
+ if (primitiveItem1 == XSConstants.ANYSIMPLETYPE_DT && primitiveItem2 == XSConstants.STRING_DT ||
+ primitiveItem1 == XSConstants.STRING_DT && primitiveItem2 == XSConstants.ANYSIMPLETYPE_DT) {
+ continue;
+ }
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the primitive type of the given type.
+ * @param valueType A value type as defined in XSConstants.
+ * @return The primitive type from which valueType was derived.
+ */
+ private static short convertToPrimitiveKind(short valueType) {
+ /** Primitive datatypes. */
+ if (valueType <= XSConstants.NOTATION_DT) {
+ return valueType;
+ }
+ /** Types derived from string. */
+ if (valueType <= XSConstants.ENTITY_DT) {
+ return XSConstants.STRING_DT;
+ }
+ /** Types derived from decimal. */
+ if (valueType <= XSConstants.POSITIVEINTEGER_DT) {
+ return XSConstants.DECIMAL_DT;
+ }
+ /** Other types. */
+ return valueType;
+ }
+
+ // XSValue methods
+
+ public Object getActualValue() {
+ return actualValue;
+ }
+
+ public short getActualValueType() {
+ return actualValueType;
+ }
+
+ public ShortList getListValueTypes() {
+ return itemValueTypes == null ? ShortListImpl.EMPTY_LIST : itemValueTypes;
+ }
+
+ public XSObjectList getMemberTypeDefinitions() {
+ if (memberTypes == null) {
+ return XSObjectListImpl.EMPTY_LIST;
+ }
+ return new XSObjectListImpl(memberTypes, memberTypes.length);
+ }
+
+ public String getNormalizedValue() {
+ return normalizedValue;
+ }
+
+ public XSSimpleTypeDefinition getTypeDefinition() {
+ return actualType;
+ }
+
+ public XSSimpleTypeDefinition getMemberTypeDefinition() {
+ return memberType;
+ }
+
+ public void copyFrom(XSValue o) {
+ if (o == null) {
+ reset();
+ }
+ else if (o instanceof ValidatedInfo) {
+ ValidatedInfo other = (ValidatedInfo)o;
+ normalizedValue = other.normalizedValue;
+ actualValue = other.actualValue;
+ actualValueType = other.actualValueType;
+ actualType = other.actualType;
+ memberType = other.memberType;
+ memberTypes = other.memberTypes;
+ itemValueTypes = other.itemValueTypes;
+ }
+ else {
+ normalizedValue = o.getNormalizedValue();
+ actualValue = o.getActualValue();
+ actualValueType = o.getActualValueType();
+ actualType = (XSSimpleType)o.getTypeDefinition();
+ memberType = (XSSimpleType)o.getMemberTypeDefinition();
+ XSSimpleType realType = memberType == null ? actualType : memberType;
+ if (realType != null && realType.getBuiltInKind() == XSConstants.LISTOFUNION_DT) {
+ XSObjectList members = o.getMemberTypeDefinitions();
+ memberTypes = new XSSimpleType[members.getLength()];
+ for (int i = 0; i < members.getLength(); i++) {
+ memberTypes[i] = (XSSimpleType)members.get(i);
+ }
+ }
+ else {
+ memberTypes = null;
+ }
+ itemValueTypes = o.getListValueTypes();
+ }
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/ValidationContext.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/ValidationContext.java
new file mode 100644
index 0000000..30cf41f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/ValidationContext.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+import java.util.Locale;
+
+/**
+ * ValidationContext has all the information required for the
+ * validation of: id, idref, entity, notation, qname
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ * @version $Id$
+ */
+public interface ValidationContext {
+ // whether to validate against facets
+ public boolean needFacetChecking();
+
+ // whether to do extra id/idref/entity checking
+ public boolean needExtraChecking();
+
+ // whether we need to normalize the value that is passed!
+ public boolean needToNormalize();
+
+ // are namespaces relevant in this context?
+ public boolean useNamespaces();
+
+ // entity
+ public boolean isEntityDeclared (String name);
+ public boolean isEntityUnparsed (String name);
+
+ // id
+ public boolean isIdDeclared (String name);
+ public void addId(String name);
+
+ // idref
+ public void addIdRef(String name);
+
+ // get symbol from symbol table
+ public String getSymbol (String symbol);
+
+ // qname
+ public String getURI(String prefix);
+
+ // Locale
+ public Locale getLocale();
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/XSFacets.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/XSFacets.java
new file mode 100644
index 0000000..df72a83
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/XSFacets.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+import java.util.Vector;
+
+import org.apache.xerces.impl.xs.util.XSObjectListImpl;
+import org.apache.xerces.xs.XSAnnotation;
+import org.apache.xerces.xs.XSObjectList;
+
+/**
+ * The class used to pass all facets to {@link XSSimpleType#applyFacets}.
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class XSFacets {
+
+ /**
+ * value of length facet.
+ */
+ public int length;
+
+ /**
+ * value of minLength facet.
+ */
+ public int minLength;
+
+ /**
+ * value of maxLength facet.
+ */
+ public int maxLength;
+
+ /**
+ * value of whiteSpace facet.
+ */
+ public short whiteSpace;
+
+ /**
+ * value of totalDigits facet.
+ */
+ public int totalDigits;
+
+ /**
+ * value of fractionDigits facet.
+ */
+ public int fractionDigits;
+
+ /**
+ * string containing value of pattern facet, for multiple patterns values
+ * are ORed together.
+ */
+ public String pattern;
+
+ /**
+ * Vector containing values of Enumeration facet, as String's.
+ */
+ public Vector enumeration;
+
+ /**
+ * An array parallel to "Vector enumeration". It contains namespace context
+ * of each enumeration value. Elements of this vector are NamespaceContext
+ * objects.
+ */
+ public Vector enumNSDecls;
+
+ /**
+ * value of maxInclusive facet.
+ */
+ public String maxInclusive;
+
+ /**
+ * value of maxExclusive facet.
+ */
+ public String maxExclusive;
+
+ /**
+ * value of minInclusive facet.
+ */
+ public String minInclusive;
+
+ /**
+ * value of minExclusive facet.
+ */
+ public String minExclusive;
+
+
+
+ public XSAnnotation lengthAnnotation;
+ public XSAnnotation minLengthAnnotation;
+ public XSAnnotation maxLengthAnnotation;
+ public XSAnnotation whiteSpaceAnnotation;
+ public XSAnnotation totalDigitsAnnotation;
+ public XSAnnotation fractionDigitsAnnotation;
+ public XSObjectListImpl patternAnnotations;
+ public XSObjectList enumAnnotations;
+ public XSAnnotation maxInclusiveAnnotation;
+ public XSAnnotation maxExclusiveAnnotation;
+ public XSAnnotation minInclusiveAnnotation;
+ public XSAnnotation minExclusiveAnnotation;
+
+ public void reset(){
+ lengthAnnotation = null;
+ minLengthAnnotation = null;
+ maxLengthAnnotation = null;
+ whiteSpaceAnnotation = null;
+ totalDigitsAnnotation = null;
+ fractionDigitsAnnotation = null;
+ patternAnnotations = null;
+ enumAnnotations = null;
+ maxInclusiveAnnotation = null;
+ maxExclusiveAnnotation = null;
+ minInclusiveAnnotation = null;
+ minExclusiveAnnotation = null;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/XSSimpleType.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/XSSimpleType.java
new file mode 100644
index 0000000..fb7e74a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/XSSimpleType.java
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv;
+
+import org.apache.xerces.xs.XSSimpleTypeDefinition;
+
+/**
+ * This interface XSSimpleType represents the simple type
+ * definition of schema component and defines methods to query the information
+ * contained.
+ * Any simple type (atomic, list or union) will implement this interface.
+ * It inherits from XSTypeDecl .
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public interface XSSimpleType extends XSSimpleTypeDefinition {
+
+ /**
+ * constants defined for the values of 'whitespace' facet.
+ * see XML Schema
+ * Part 2: Datatypes
+ */
+ /** preserve the white spaces */
+ public static final short WS_PRESERVE = 0;
+ /** replace the white spaces */
+ public static final short WS_REPLACE = 1;
+ /** collapse the white spaces */
+ public static final short WS_COLLAPSE = 2;
+
+ /**
+ * Constant defined for the primitive built-in simple tpyes.
+ * see
+ * XML Schema Part 2: Datatypes
+ */
+ /** "string" type */
+ public static final short PRIMITIVE_STRING = 1;
+ /** "boolean" type */
+ public static final short PRIMITIVE_BOOLEAN = 2;
+ /** "decimal" type */
+ public static final short PRIMITIVE_DECIMAL = 3;
+ /** "float" type */
+ public static final short PRIMITIVE_FLOAT = 4;
+ /** "double" type */
+ public static final short PRIMITIVE_DOUBLE = 5;
+ /** "duration" type */
+ public static final short PRIMITIVE_DURATION = 6;
+ /** "dataTime" type */
+ public static final short PRIMITIVE_DATETIME = 7;
+ /** "time" type */
+ public static final short PRIMITIVE_TIME = 8;
+ /** "date" type */
+ public static final short PRIMITIVE_DATE = 9;
+ /** "gYearMonth" type */
+ public static final short PRIMITIVE_GYEARMONTH = 10;
+ /** "gYear" type */
+ public static final short PRIMITIVE_GYEAR = 11;
+ /** "gMonthDay" type */
+ public static final short PRIMITIVE_GMONTHDAY = 12;
+ /** "gDay" type */
+ public static final short PRIMITIVE_GDAY = 13;
+ /** "gMonth" type */
+ public static final short PRIMITIVE_GMONTH = 14;
+ /** "hexBinary" type */
+ public static final short PRIMITIVE_HEXBINARY = 15;
+ /** "base64Binary" type */
+ public static final short PRIMITIVE_BASE64BINARY = 16;
+ /** "anyURI" type */
+ public static final short PRIMITIVE_ANYURI = 17;
+ /** "QName" type */
+ public static final short PRIMITIVE_QNAME = 18;
+ /** "precisionDecimal" type */
+ public static final short PRIMITIVE_PRECISIONDECIMAL = 19;
+ /** "NOTATION" type */
+ public static final short PRIMITIVE_NOTATION = 20;
+
+ /**
+ * return an ID representing the built-in primitive base type.
+ * REVISIT: This method is (currently) for internal use only.
+ * the constants returned from this method are not finalized yet.
+ * the names and values might change in the further.
+ *
+ * @return an ID representing the built-in primitive base type
+ */
+ public short getPrimitiveKind();
+
+ /**
+ * validate a given string against this simple type.
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ * @param validatedInfo used to store validation result
+ *
+ * @return the actual value (QName, Boolean) of the string value
+ */
+ public Object validate(String content, ValidationContext context, ValidatedInfo validatedInfo)
+ throws InvalidDatatypeValueException;
+
+ /**
+ * validate a given string value, represented by content.toString().
+ * note that if content is a StringBuffer, for performance reasons,
+ * it's possible that the content of the string buffer is modified.
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ * @param validatedInfo used to store validation result
+ *
+ * @return the actual value (QName, Boolean) of the string value
+ */
+ public Object validate(Object content, ValidationContext context, ValidatedInfo validatedInfo)
+ throws InvalidDatatypeValueException;
+
+ /**
+ * Validate an actual value against this simple type.
+ *
+ * @param context the validation context
+ * @param validatedInfo used to provide the actual value and member types
+ * @exception InvalidDatatypeValueException exception for invalid values.
+ */
+ public void validate(ValidationContext context, ValidatedInfo validatedInfo)
+ throws InvalidDatatypeValueException;
+
+ /**
+ * If this type is created from restriction, then some facets can be applied
+ * to the simple type. XSFacets is used to pass the value of
+ * different facets.
+ *
+ * @param facets the value of all the facets
+ * @param presentFacet bit combination value of the costraining facet
+ * constants which are present.
+ * @param fixedFacet bit combination value of the costraining facet
+ * constants which are fixed.
+ * @param context the validation context
+ * @exception InvalidDatatypeFacetException exception for invalid facet values.
+ */
+ public void applyFacets(XSFacets facets, short presentFacet, short fixedFacet, ValidationContext context)
+ throws InvalidDatatypeFacetException;
+
+ /**
+ * Check whether two actual values are equal.
+ *
+ * @param value1 the first value
+ * @param value2 the second value
+ * @return true if the two value are equal
+ */
+ public boolean isEqual(Object value1, Object value2);
+
+ /**
+ * Check the order of the two actual values. (May not be supported by all
+ * simple types.
+ * REVISIT: Andy believes that a compare() method is necessary.
+ * I don't see the necessity for schema (the only place where we
+ * need to compare two values is to check min/maxIn/Exclusive
+ * facets, but we only need a private method for this case.)
+ * But Andy thinks XPATH potentially needs this compare() method.
+ *
+ * @param value1 the first value
+ * @prarm value2 the second value
+ * @return > 0 if value1 > value2
+ * = 0 if value1 == value2
+ * < = if value1 < value2
+ */
+ //public short compare(Object value1, Object value2);
+
+ /**
+ * Check whether this type is or is derived from ID.
+ * REVISIT: this method makes ID special, which is not a good design.
+ * but since ID is not a primitive, there doesn't seem to be a
+ * clean way of doing it except to define special method like this.
+ *
+ * @return whether this simple type is or is derived from ID.
+ */
+ public boolean isIDType();
+
+ /**
+ * Return the whitespace corresponding to this datatype.
+ *
+ * @return valid values are WS_PRESERVE, WS_REPLACE, WS_COLLAPSE.
+ * @exception DatatypeException
+ * union datatypes don't have whitespace facet associated with them
+ */
+ public short getWhitespace() throws DatatypeException;
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/DTDDVFactoryImpl.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/DTDDVFactoryImpl.java
new file mode 100644
index 0000000..efff35c
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/DTDDVFactoryImpl.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.dtd;
+
+import java.util.Hashtable;
+
+import org.apache.xerces.impl.dv.DTDDVFactory;
+import org.apache.xerces.impl.dv.DatatypeValidator;
+
+/**
+ * the factory to create/return built-in schema DVs and create user-defined DVs
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class DTDDVFactoryImpl extends DTDDVFactory {
+
+ static final Hashtable fBuiltInTypes = new Hashtable();
+ static {
+ createBuiltInTypes();
+ }
+
+ /**
+ * return a dtd type of the given name
+ *
+ * @param name the name of the datatype
+ * @return the datatype validator of the given name
+ */
+ public DatatypeValidator getBuiltInDV(String name) {
+ return (DatatypeValidator)fBuiltInTypes.get(name);
+ }
+
+ /**
+ * get all built-in DVs, which are stored in a hashtable keyed by the name
+ *
+ * @return a hashtable which contains all datatypes
+ */
+ public Hashtable getBuiltInTypes() {
+ return (Hashtable)fBuiltInTypes.clone();
+ }
+
+ // create all built-in types
+ static void createBuiltInTypes() {
+
+ DatatypeValidator dvTemp;
+
+ fBuiltInTypes.put("string", new StringDatatypeValidator());
+ fBuiltInTypes.put("ID", new IDDatatypeValidator());
+ dvTemp = new IDREFDatatypeValidator();
+ fBuiltInTypes.put("IDREF", dvTemp);
+ fBuiltInTypes.put("IDREFS", new ListDatatypeValidator(dvTemp));
+ dvTemp = new ENTITYDatatypeValidator();
+ fBuiltInTypes.put("ENTITY", new ENTITYDatatypeValidator());
+ fBuiltInTypes.put("ENTITIES", new ListDatatypeValidator(dvTemp));
+ fBuiltInTypes.put("NOTATION", new NOTATIONDatatypeValidator());
+ dvTemp = new NMTOKENDatatypeValidator();
+ fBuiltInTypes.put("NMTOKEN", dvTemp);
+ fBuiltInTypes.put("NMTOKENS", new ListDatatypeValidator(dvTemp));
+
+ }//createBuiltInTypes()
+
+}// DTDDVFactoryImpl
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/ENTITYDatatypeValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/ENTITYDatatypeValidator.java
new file mode 100644
index 0000000..ed748b5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/ENTITYDatatypeValidator.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.dtd;
+
+import org.apache.xerces.impl.dv.DatatypeValidator;
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * ENTITYDatatypeValidator implements the
+ * DatattypeValidator interface.
+ * This validator embodies the ENTITY attribute type
+ * from XML1.0 recommendation.
+ * The Value space of ENTITY is the set of all strings
+ * that match the NCName production and have been
+ * declared as an unparsed entity in a document
+ * type definition.
+ * The Lexical space of Entity is the set of all
+ * strings that match the NCName production.
+ * The value space of ENTITY is scoped to a specific
+ * instance document.
+ *
+ * @xerces.internal
+ *
+ * @author Jeffrey Rodriguez, IBM
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class ENTITYDatatypeValidator implements DatatypeValidator {
+
+ // construct an ENTITY datatype validator
+ public ENTITYDatatypeValidator() {
+ }
+
+ /**
+ * Checks that "content" string is valid ID value.
+ * If invalid a Datatype validation exception is thrown.
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ * @throws InvalidDatatypeException if the content is
+ * invalid according to the rules for the validators
+ * @see InvalidDatatypeValueException
+ */
+ public void validate(String content, ValidationContext context) throws InvalidDatatypeValueException {
+
+ if (!context.isEntityUnparsed(content))
+ throw new InvalidDatatypeValueException("ENTITYNotUnparsed", new Object[]{content});
+
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/IDDatatypeValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/IDDatatypeValidator.java
new file mode 100644
index 0000000..7057fd5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/IDDatatypeValidator.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.dtd;
+
+import org.apache.xerces.impl.dv.DatatypeValidator;
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.XMLChar;
+
+/**
+ * IDDatatypeValidator - ID represents the ID attribute
+ * type from XML 1.0 Recommendation. The value space
+ * od ID is the set of all strings that match the
+ * NCName production and have been used in an XML
+ * document. The lexical space of ID is the set of all
+ * strings that match the NCName production.
+ * The value space of ID is scoped to a specific
+ * instance document.
+ * The following constraint applies:
+ * An ID must not appear more than once in an XML
+ * document as a value of this type; i.e., ID values
+ * must uniquely identify the elements which bear
+ * them.
+ *
+ * @xerces.internal
+ *
+ * @author Jeffrey Rodriguez, IBM
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class IDDatatypeValidator implements DatatypeValidator {
+
+ // construct an ID datatype validator
+ public IDDatatypeValidator() {
+ }
+
+ /**
+ * Checks that "content" string is valid ID value.
+ * If invalid a Datatype validation exception is thrown.
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ * @throws InvalidDatatypeException if the content is
+ * invalid according to the rules for the validators
+ * @see InvalidDatatypeValueException
+ */
+ public void validate(String content, ValidationContext context) throws InvalidDatatypeValueException {
+
+ //Check if is valid key-[81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
+ if(context.useNamespaces()) {
+ if (!XMLChar.isValidNCName(content)) {
+ throw new InvalidDatatypeValueException("IDInvalidWithNamespaces", new Object[]{content});
+ }
+ }
+ else {
+ if (!XMLChar.isValidName(content)) {
+ throw new InvalidDatatypeValueException("IDInvalid", new Object[]{content});
+ }
+ }
+
+ if (context.isIdDeclared(content)) {
+ throw new InvalidDatatypeValueException("IDNotUnique", new Object[]{content});
+ }
+
+ context.addId(content);
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/IDREFDatatypeValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/IDREFDatatypeValidator.java
new file mode 100644
index 0000000..fa6685a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/IDREFDatatypeValidator.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.dtd;
+
+import org.apache.xerces.impl.dv.DatatypeValidator;
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.XMLChar;
+
+/**
+ * IDREFDatatypeValidator - represents the IDREFS
+ * attribute type from XML 1.0 recommendation. The
+ * Value Space of IDREF is the set of all strings
+ * that match the NCName production and have been
+ * used in an XML Document as the value of an element
+ * or attribute of Type ID. The Lexical space of
+ * IDREF is the set of strings that match the NCName
+ * production.
+ * The Value space of IDREF is scoped to a specific
+ * instance document
+ *
+ * @xerces.internal
+ *
+ * @author Jeffrey Rodriguez, IBM
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class IDREFDatatypeValidator implements DatatypeValidator {
+
+ // construct an IDREF datatype validator
+ public IDREFDatatypeValidator() {
+ }
+
+ /**
+ * Checks that "content" string is valid IDREF value.
+ * If invalid a Datatype validation exception is thrown.
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ * @throws InvalidDatatypeException if the content is
+ * invalid according to the rules for the validators
+ * @see InvalidDatatypeValueException
+ */
+ public void validate(String content, ValidationContext context) throws InvalidDatatypeValueException {
+
+ //Check if is valid key-[81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
+ if(context.useNamespaces()) {
+ if (!XMLChar.isValidNCName(content)) {
+ throw new InvalidDatatypeValueException("IDREFInvalidWithNamespaces", new Object[]{content});
+ }
+ }
+ else {
+ if (!XMLChar.isValidName(content)) {
+ throw new InvalidDatatypeValueException("IDREFInvalid", new Object[]{content});
+ }
+ }
+
+ context.addIdRef(content);
+
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/ListDatatypeValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/ListDatatypeValidator.java
new file mode 100644
index 0000000..a7a1988
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/ListDatatypeValidator.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.dtd;
+
+import java.util.StringTokenizer;
+
+import org.apache.xerces.impl.dv.DatatypeValidator;
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * For list types: ENTITIES, IDREFS, NMTOKENS.
+ *
+ * @xerces.internal
+ *
+ * @author Jeffrey Rodriguez, IBM
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class ListDatatypeValidator implements DatatypeValidator {
+
+ // the type of items in the list
+ final DatatypeValidator fItemValidator;
+
+ // construct a list datatype validator
+ public ListDatatypeValidator(DatatypeValidator itemDV) {
+ fItemValidator = itemDV;
+ }
+
+ /**
+ * Checks that "content" string is valid.
+ * If invalid a Datatype validation exception is thrown.
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ * @throws InvalidDatatypeException if the content is
+ * invalid according to the rules for the validators
+ * @see InvalidDatatypeValueException
+ */
+ public void validate(String content, ValidationContext context) throws InvalidDatatypeValueException {
+
+ StringTokenizer parsedList = new StringTokenizer(content," ");
+ int numberOfTokens = parsedList.countTokens();
+ if (numberOfTokens == 0) {
+ throw new InvalidDatatypeValueException("EmptyList", null);
+ }
+ //Check each token in list against base type
+ while (parsedList.hasMoreTokens()) {
+ this.fItemValidator.validate(parsedList.nextToken(), context);
+ }
+ }
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/NMTOKENDatatypeValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/NMTOKENDatatypeValidator.java
new file mode 100644
index 0000000..3b9cb3e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/NMTOKENDatatypeValidator.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.dtd;
+
+import org.apache.xerces.impl.dv.DatatypeValidator;
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.XMLChar;
+
+/**
+ * NMTOKEN datatype validator.
+ *
+ * @xerces.internal
+ *
+ * @author Jeffrey Rodriguez, IBM
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class NMTOKENDatatypeValidator implements DatatypeValidator {
+
+ // construct a NMTOKEN datatype validator
+ public NMTOKENDatatypeValidator() {
+ }
+
+ /**
+ * Checks that "content" string is valid NMTOKEN value.
+ * If invalid a Datatype validation exception is thrown.
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ * @throws InvalidDatatypeException if the content is
+ * invalid according to the rules for the validators
+ * @see InvalidDatatypeValueException
+ */
+ public void validate(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ if (!XMLChar.isValidNmtoken(content)) {
+ throw new InvalidDatatypeValueException("NMTOKENInvalid", new Object[]{content});
+ }
+ }
+
+} // class NMTOKENDatatypeValidator
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/NOTATIONDatatypeValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/NOTATIONDatatypeValidator.java
new file mode 100644
index 0000000..e5b0c8a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/NOTATIONDatatypeValidator.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.dtd;
+
+import org.apache.xerces.impl.dv.DatatypeValidator;
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * NOTATIONValidator defines the interface that data type validators must obey.
+ * These validators can be supplied by the application writer and may be useful as
+ * standalone code as well as plugins to the validator architecture.
+ *
+ * @xerces.internal
+ *
+ * @author Jeffrey Rodriguez, IBM
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+ public class NOTATIONDatatypeValidator implements DatatypeValidator {
+
+ // construct a NOTATION datatype validator
+ public NOTATIONDatatypeValidator() {
+ }
+
+ /**
+ * Checks that "content" string is valid NOTATION value.
+ * If invalid a Datatype validation exception is thrown.
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ * @throws InvalidDatatypeException if the content is
+ * invalid according to the rules for the validators
+ * @see InvalidDatatypeValueException
+ */
+ public void validate(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/StringDatatypeValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/StringDatatypeValidator.java
new file mode 100644
index 0000000..58bf330
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/StringDatatypeValidator.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.dtd;
+
+import org.apache.xerces.impl.dv.DatatypeValidator;
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * StringValidator validates that XML content is a W3C string type.
+ * The string datatype represents character strings in XML. The
+ * value space of string is the set of finite-length sequences
+ * of characters (as defined in [XML 1.0 Recommendation
+ * (Second Edition)]) that match the Char production
+ * from [XML 1.0 Recommendation (Second Edition)].
+ * A character is an atomic unit of communication; it
+ * is not further specified except to note that every
+ * character has a corresponding Universal Code Set
+ * code point ([ISO 10646],[Unicode] and [Unicode3]),
+ * which is an integer.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class StringDatatypeValidator implements DatatypeValidator {
+
+ // construct a string datatype validator
+ public StringDatatypeValidator() {
+ }
+
+ /**
+ * Checks that "content" string is valid string value.
+ * If invalid a Datatype validation exception is thrown.
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ * @throws InvalidDatatypeException if the content is
+ * invalid according to the rules for the validators
+ * @see InvalidDatatypeValueException
+ */
+ public void validate(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/XML11DTDDVFactoryImpl.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/XML11DTDDVFactoryImpl.java
new file mode 100644
index 0000000..f1d4d1e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/XML11DTDDVFactoryImpl.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.dtd;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.xerces.impl.dv.DatatypeValidator;
+
+/**
+ * the factory to create/return built-in XML 1.1 DVs and create user-defined DVs
+ *
+ * @xerces.internal
+ *
+ * @author Neil Graham, IBM
+ *
+ * @version $Id$
+ */
+public class XML11DTDDVFactoryImpl extends DTDDVFactoryImpl {
+
+ static final Hashtable fXML11BuiltInTypes = new Hashtable();
+
+ /**
+ * return a dtd type of the given name
+ * This will call the super class if and only if it does not
+ * recognize the passed-in name.
+ *
+ * @param name the name of the datatype
+ * @return the datatype validator of the given name
+ */
+ public DatatypeValidator getBuiltInDV(String name) {
+ if(fXML11BuiltInTypes.get(name) != null) {
+ return (DatatypeValidator)fXML11BuiltInTypes.get(name);
+ }
+ return (DatatypeValidator)fBuiltInTypes.get(name);
+ }
+
+ /**
+ * get all built-in DVs, which are stored in a hashtable keyed by the name
+ * New XML 1.1 datatypes are inserted.
+ *
+ * @return a hashtable which contains all datatypes
+ */
+ public Hashtable getBuiltInTypes() {
+ Hashtable toReturn = (Hashtable)fBuiltInTypes.clone();
+ Iterator entries = fXML11BuiltInTypes.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ Object key = entry.getKey();
+ Object dv = entry.getValue();
+ toReturn.put(key, dv);
+ }
+ return toReturn;
+ }
+
+ static {
+ fXML11BuiltInTypes.put("XML11ID", new XML11IDDatatypeValidator());
+ DatatypeValidator dvTemp = new XML11IDREFDatatypeValidator();
+ fXML11BuiltInTypes.put("XML11IDREF", dvTemp);
+ fXML11BuiltInTypes.put("XML11IDREFS", new ListDatatypeValidator(dvTemp));
+ dvTemp = new XML11NMTOKENDatatypeValidator();
+ fXML11BuiltInTypes.put("XML11NMTOKEN", dvTemp);
+ fXML11BuiltInTypes.put("XML11NMTOKENS", new ListDatatypeValidator(dvTemp));
+ } //
+
+
+}//XML11DTDDVFactoryImpl
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/XML11IDDatatypeValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/XML11IDDatatypeValidator.java
new file mode 100644
index 0000000..9a28664
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/XML11IDDatatypeValidator.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.dtd;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.XML11Char;
+
+/**
+ * IDDatatypeValidator - ID represents the ID attribute
+ * type from XML 1.1 Recommendation. The value space
+ * of ID is the set of all strings that match the
+ * NCName production and have been used in an XML
+ * document. The lexical space of ID is the set of all
+ * strings that match the NCName production.
+ * The value space of ID is scoped to a specific
+ * instance document.
+ * The following constraint applies:
+ * An ID must not appear more than once in an XML
+ * document as a value of this type; i.e., ID values
+ * must uniquely identify the elements which bear
+ * them.
+ *
+ * @xerces.internal
+ *
+ * @author Jeffrey Rodriguez, IBM
+ * @author Sandy Gao, IBM
+ * @author Neil Graham, IBM
+ *
+ * @version $Id$
+ */
+public class XML11IDDatatypeValidator extends IDDatatypeValidator {
+
+ // construct an ID datatype validator
+ public XML11IDDatatypeValidator() {
+ super();
+ }
+
+ /**
+ * Checks that "content" string is valid ID value.
+ * If invalid a Datatype validation exception is thrown.
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ * @throws InvalidDatatypeException if the content is
+ * invalid according to the rules for the validators
+ * @see InvalidDatatypeValueException
+ */
+ public void validate(String content, ValidationContext context) throws InvalidDatatypeValueException {
+
+ //Check if is valid key-[81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
+ if(context.useNamespaces()) {
+ if (!XML11Char.isXML11ValidNCName(content)) {
+ throw new InvalidDatatypeValueException("IDInvalidWithNamespaces", new Object[]{content});
+ }
+ }
+ else {
+ if (!XML11Char.isXML11ValidName(content)) {
+ throw new InvalidDatatypeValueException("IDInvalid", new Object[]{content});
+ }
+ }
+
+ if (context.isIdDeclared(content)) {
+ throw new InvalidDatatypeValueException("IDNotUnique", new Object[]{content});
+ }
+
+ context.addId(content);
+ }
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/XML11IDREFDatatypeValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/XML11IDREFDatatypeValidator.java
new file mode 100644
index 0000000..41000c5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/XML11IDREFDatatypeValidator.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.dtd;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.XML11Char;
+
+/**
+ * IDREFDatatypeValidator - represents the IDREFS
+ * attribute type from XML 1.1 recommendation. The
+ * Value Space of IDREF is the set of all strings
+ * that match the NCName production and have been
+ * used in an XML Document as the value of an element
+ * or attribute of Type ID. The Lexical space of
+ * IDREF is the set of strings that match the NCName
+ * production.
+ * The Value space of IDREF is scoped to a specific
+ * instance document
+ *
+ * @xerces.internal
+ *
+ * @author Jeffrey Rodriguez, IBM
+ * @author Sandy Gao, IBM
+ * @author Neil Graham, IBM
+ *
+ * @version $Id$
+ */
+public class XML11IDREFDatatypeValidator extends IDREFDatatypeValidator {
+
+ // construct an IDREF datatype validator
+ public XML11IDREFDatatypeValidator() {
+ super();
+ }
+
+ /**
+ * Checks that "content" string is valid IDREF value.
+ * If invalid a Datatype validation exception is thrown.
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ * @throws InvalidDatatypeException if the content is
+ * invalid according to the rules for the validators
+ * @see InvalidDatatypeValueException
+ */
+ public void validate(String content, ValidationContext context) throws InvalidDatatypeValueException {
+
+ //Check if is valid key-[81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
+ if(context.useNamespaces()) {
+ if (!XML11Char.isXML11ValidNCName(content)) {
+ throw new InvalidDatatypeValueException("IDREFInvalidWithNamespaces", new Object[]{content});
+ }
+ }
+ else {
+ if (!XML11Char.isXML11ValidName(content)) {
+ throw new InvalidDatatypeValueException("IDREFInvalid", new Object[]{content});
+ }
+ }
+
+ context.addIdRef(content);
+
+ }
+
+}
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/XML11NMTOKENDatatypeValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/XML11NMTOKENDatatypeValidator.java
new file mode 100644
index 0000000..3d226d9
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/dtd/XML11NMTOKENDatatypeValidator.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.dtd;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.XML11Char;
+
+/**
+ * NMTOKEN datatype validator for NMTokens from XML 1.1.
+ *
+ * @xerces.internal
+ *
+ * @author Jeffrey Rodriguez, IBM
+ * @author Sandy Gao, IBM
+ * @author Neil Graham, IBM
+ *
+ * @version $Id$
+ */
+public class XML11NMTOKENDatatypeValidator extends NMTOKENDatatypeValidator {
+
+ // construct a NMTOKEN datatype validator
+ public XML11NMTOKENDatatypeValidator() {
+ super();
+ }
+
+ /**
+ * Checks that "content" string is valid NMTOKEN value.
+ * If invalid a Datatype validation exception is thrown.
+ *
+ * @param content the string value that needs to be validated
+ * @param context the validation context
+ * @throws InvalidDatatypeException if the content is
+ * invalid according to the rules for the validators
+ * @see InvalidDatatypeValueException
+ */
+ public void validate(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ if (!XML11Char.isXML11ValidNmtoken(content)) {
+ throw new InvalidDatatypeValueException("NMTOKENInvalid", new Object[]{content});
+ }
+ }
+
+} // class XML11NMTOKENDatatypeValidator
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/util/Base64.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/util/Base64.java
new file mode 100644
index 0000000..61c6f8f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/util/Base64.java
@@ -0,0 +1,305 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.util;
+
+/**
+ * This class provides encode/decode for RFC 2045 Base64 as
+ * defined by RFC 2045, N. Freed and N. Borenstein.
+ * RFC 2045: Multipurpose Internet Mail Extensions (MIME)
+ * Part One: Format of Internet Message Bodies. Reference
+ * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt
+ * This class is used by XML Schema binary format validation
+ *
+ * This implementation does not encode/decode streaming
+ * data. You need the data that you will encode/decode
+ * already on a byte arrray.
+ *
+ * @xerces.internal
+ *
+ * @author Jeffrey Rodriguez
+ * @author Sandy Gao
+ * @version $Id$
+ */
+public final class Base64 {
+
+ static private final int BASELENGTH = 128;
+ static private final int LOOKUPLENGTH = 64;
+ static private final int TWENTYFOURBITGROUP = 24;
+ static private final int EIGHTBIT = 8;
+ static private final int SIXTEENBIT = 16;
+ static private final int SIXBIT = 6;
+ static private final int FOURBYTE = 4;
+ static private final int SIGN = -128;
+ static private final char PAD = '=';
+ static private final boolean fDebug = false;
+ static final private byte [] base64Alphabet = new byte[BASELENGTH];
+ static final private char [] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
+
+ static {
+
+ for (int i = 0; i < BASELENGTH; ++i) {
+ base64Alphabet[i] = -1;
+ }
+ for (int i = 'Z'; i >= 'A'; i--) {
+ base64Alphabet[i] = (byte) (i-'A');
+ }
+ for (int i = 'z'; i>= 'a'; i--) {
+ base64Alphabet[i] = (byte) ( i-'a' + 26);
+ }
+
+ for (int i = '9'; i >= '0'; i--) {
+ base64Alphabet[i] = (byte) (i-'0' + 52);
+ }
+
+ base64Alphabet['+'] = 62;
+ base64Alphabet['/'] = 63;
+
+ for (int i = 0; i<=25; i++)
+ lookUpBase64Alphabet[i] = (char)('A'+i);
+
+ for (int i = 26, j = 0; i<=51; i++, j++)
+ lookUpBase64Alphabet[i] = (char)('a'+ j);
+
+ for (int i = 52, j = 0; i<=61; i++, j++)
+ lookUpBase64Alphabet[i] = (char)('0' + j);
+ lookUpBase64Alphabet[62] = (char)'+';
+ lookUpBase64Alphabet[63] = (char)'/';
+
+ }
+
+ protected static boolean isWhiteSpace(char octect) {
+ return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
+ }
+
+ protected static boolean isPad(char octect) {
+ return (octect == PAD);
+ }
+
+ protected static boolean isData(char octect) {
+ return (octect < BASELENGTH && base64Alphabet[octect] != -1);
+ }
+
+ protected static boolean isBase64(char octect) {
+ return (isWhiteSpace(octect) || isPad(octect) || isData(octect));
+ }
+
+ /**
+ * Encodes hex octects into Base64
+ *
+ * @param binaryData Array containing binaryData
+ * @return Encoded Base64 array
+ */
+ public static String encode(byte[] binaryData) {
+
+ if (binaryData == null)
+ return null;
+
+ int lengthDataBits = binaryData.length*EIGHTBIT;
+ if (lengthDataBits == 0) {
+ return "";
+ }
+
+ int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP;
+ int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP;
+ int numberQuartet = fewerThan24bits != 0 ? numberTriplets+1 : numberTriplets;
+ char encodedData[] = null;
+
+ encodedData = new char[numberQuartet*4];
+
+ byte k=0, l=0, b1=0,b2=0,b3=0;
+
+ int encodedIndex = 0;
+ int dataIndex = 0;
+ if (fDebug) {
+ System.out.println("number of triplets = " + numberTriplets );
+ }
+
+ for (int i=0; i>2) );
+ }
+ byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[ val1 ];
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[ k<<4 ];
+ encodedData[encodedIndex++] = PAD;
+ encodedData[encodedIndex++] = PAD;
+ } else if (fewerThan24bits == SIXTEENBIT) {
+ b1 = binaryData[dataIndex];
+ b2 = binaryData[dataIndex +1 ];
+ l = ( byte ) ( b2 &0x0f );
+ k = ( byte ) ( b1 &0x03 );
+
+ byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
+ byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
+
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[ val1 ];
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[ val2 | ( k<<4 )];
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[ l<<2 ];
+ encodedData[encodedIndex++] = PAD;
+ }
+
+ return new String(encodedData);
+ }
+
+ /**
+ * Decodes Base64 data into octects
+ *
+ * @param encoded string containing Base64 data
+ * @return Array containind decoded data.
+ */
+ public static byte[] decode(String encoded) {
+
+ if (encoded == null)
+ return null;
+
+ char[] base64Data = encoded.toCharArray();
+ // remove white spaces
+ int len = removeWhiteSpace(base64Data);
+
+ if (len%FOURBYTE != 0) {
+ return null;//should be divisible by four
+ }
+
+ int numberQuadruple = (len/FOURBYTE );
+
+ if (numberQuadruple == 0)
+ return new byte[0];
+
+ byte decodedData[] = null;
+ byte b1=0,b2=0,b3=0,b4=0;
+ char d1=0,d2=0,d3=0,d4=0;
+
+ int i = 0;
+ int encodedIndex = 0;
+ int dataIndex = 0;
+ decodedData = new byte[ (numberQuadruple)*3];
+
+ for (; i>4 ) ;
+ decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
+ decodedData[encodedIndex++] = (byte)( b3<<6 | b4 );
+ }
+
+ if (!isData( (d1 = base64Data[dataIndex++]) ) ||
+ !isData( (d2 = base64Data[dataIndex++]) )) {
+ return null;//if found "no data" just return null
+ }
+
+ b1 = base64Alphabet[d1];
+ b2 = base64Alphabet[d2];
+
+ d3 = base64Data[dataIndex++];
+ d4 = base64Data[dataIndex++];
+ if (!isData( (d3 ) ) ||
+ !isData( (d4 ) )) {//Check if they are PAD characters
+ if (isPad( d3 ) && isPad( d4)) { //Two PAD e.g. 3c[Pad][Pad]
+ if ((b2 & 0xf) != 0)//last 4 bits should be zero
+ return null;
+ byte[] tmp = new byte[ i*3 + 1 ];
+ System.arraycopy( decodedData, 0, tmp, 0, i*3 );
+ tmp[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
+ return tmp;
+ } else if (!isPad( d3) && isPad(d4)) { //One PAD e.g. 3cQ[Pad]
+ b3 = base64Alphabet[ d3 ];
+ if ((b3 & 0x3 ) != 0)//last 2 bits should be zero
+ return null;
+ byte[] tmp = new byte[ i*3 + 2 ];
+ System.arraycopy( decodedData, 0, tmp, 0, i*3 );
+ tmp[encodedIndex++] = (byte)( b1 <<2 | b2>>4 );
+ tmp[encodedIndex] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
+ return tmp;
+ } else {
+ return null;//an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data
+ }
+ } else { //No PAD e.g 3cQl
+ b3 = base64Alphabet[ d3 ];
+ b4 = base64Alphabet[ d4 ];
+ decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ;
+ decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
+ decodedData[encodedIndex++] = (byte)( b3<<6 | b4 );
+
+ }
+
+ return decodedData;
+ }
+
+ /**
+ * remove WhiteSpace from MIME containing encoded Base64 data.
+ *
+ * @param data the byte array of base64 data (with WS)
+ * @return the new length
+ */
+ protected static int removeWhiteSpace(char[] data) {
+ if (data == null)
+ return 0;
+
+ // count characters that's not whitespace
+ int newSize = 0;
+ int len = data.length;
+ for (int i = 0; i < len; i++) {
+ if (!isWhiteSpace(data[i]))
+ data[newSize++] = data[i];
+ }
+ return newSize;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/util/ByteListImpl.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/util/ByteListImpl.java
new file mode 100644
index 0000000..f714d7f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/util/ByteListImpl.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.util;
+
+import java.util.AbstractList;
+
+import org.apache.xerces.xs.XSException;
+import org.apache.xerces.xs.datatypes.ByteList;
+
+/**
+ * Implementation of org.apache.xerces.xs.datatypes.ByteList .
+ *
+ * @xerces.internal
+ *
+ * @author Ankit Pasricha, IBM
+ *
+ * @version $Id$
+ */
+public class ByteListImpl extends AbstractList implements ByteList {
+
+ // actually data stored in a byte array
+ protected final byte[] data;
+
+ // canonical representation of the data
+ protected String canonical;
+
+ public ByteListImpl(byte[] data) {
+ this.data = data;
+ }
+
+ /**
+ * The number of byte s in the list. The range of
+ * valid child object indices is 0 to length-1 inclusive.
+ */
+ public int getLength() {
+ return data.length;
+ }
+
+ /**
+ * Checks if the byte item is a
+ * member of this list.
+ * @param item byte whose presence in this list
+ * is to be tested.
+ * @return True if this list contains the byte
+ * item .
+ */
+ public boolean contains(byte item) {
+ for (int i = 0; i < data.length; ++i) {
+ if (data[i] == item) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the index th item in the collection. The index
+ * starts at 0.
+ * @param index index into the collection.
+ * @return The byte at the index th
+ * position in the ByteList .
+ * @exception XSException
+ * INDEX_SIZE_ERR: if index is greater than or equal to the
+ * number of objects in the list.
+ */
+ public byte item(int index)
+ throws XSException {
+
+ if(index < 0 || index > data.length - 1) {
+ throw new XSException(XSException.INDEX_SIZE_ERR, null);
+ }
+ return data[index];
+ }
+
+ /*
+ * List methods
+ */
+
+ public Object get(int index) {
+ if (index >= 0 && index < data.length) {
+ return new Byte(data[index]);
+ }
+ throw new IndexOutOfBoundsException("Index: " + index);
+ }
+
+ public int size() {
+ return getLength();
+ }
+
+ public byte[] toByteArray() {
+ byte[] ret = new byte[data.length];
+ System.arraycopy(data, 0, ret, 0, data.length);
+ return ret;
+ }
+}
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/util/HexBin.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/util/HexBin.java
new file mode 100644
index 0000000..11b5f8d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/util/HexBin.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.util;
+
+/**
+ * format validation
+ *
+ * This class encodes/decodes hexadecimal data
+ *
+ * @xerces.internal
+ *
+ * @author Jeffrey Rodriguez
+ * @version $Id$
+ */
+public final class HexBin {
+ static private final int BASELENGTH = 128;
+ static private final int LOOKUPLENGTH = 16;
+ static final private byte [] hexNumberTable = new byte[BASELENGTH];
+ static final private char [] lookUpHexAlphabet = new char[LOOKUPLENGTH];
+
+
+ static {
+ for (int i = 0; i < BASELENGTH; i++ ) {
+ hexNumberTable[i] = -1;
+ }
+ for ( int i = '9'; i >= '0'; i--) {
+ hexNumberTable[i] = (byte) (i-'0');
+ }
+ for ( int i = 'F'; i>= 'A'; i--) {
+ hexNumberTable[i] = (byte) ( i-'A' + 10 );
+ }
+ for ( int i = 'f'; i>= 'a'; i--) {
+ hexNumberTable[i] = (byte) ( i-'a' + 10 );
+ }
+
+ for(int i = 0; i<10; i++ ) {
+ lookUpHexAlphabet[i] = (char)('0'+i);
+ }
+ for(int i = 10; i<=15; i++ ) {
+ lookUpHexAlphabet[i] = (char)('A'+i -10);
+ }
+ }
+
+ /**
+ * Encode a byte array to hex string
+ *
+ * @param binaryData array of byte to encode
+ * @return return encoded string
+ */
+ static public String encode(byte[] binaryData) {
+ if (binaryData == null)
+ return null;
+ int lengthData = binaryData.length;
+ int lengthEncode = lengthData * 2;
+ char[] encodedData = new char[lengthEncode];
+ int temp;
+ for (int i = 0; i < lengthData; i++) {
+ temp = binaryData[i];
+ if (temp < 0)
+ temp += 256;
+ encodedData[i*2] = lookUpHexAlphabet[temp >> 4];
+ encodedData[i*2+1] = lookUpHexAlphabet[temp & 0xf];
+ }
+ return new String(encodedData);
+ }
+
+ /**
+ * Decode hex string to a byte array
+ *
+ * @param encoded encoded string
+ * @return return array of byte to encode
+ */
+ static public byte[] decode(String encoded) {
+ if (encoded == null)
+ return null;
+ int lengthData = encoded.length();
+ if (lengthData % 2 != 0)
+ return null;
+
+ char[] binaryData = encoded.toCharArray();
+ int lengthDecode = lengthData / 2;
+ byte[] decodedData = new byte[lengthDecode];
+ byte temp1, temp2;
+ char tempChar;
+ for( int i = 0; i=(date2 with time zone +14)
+ //
+ cloneDate(date2, tempDate); //clones date1 value to global temporary storage: tempDate
+ tempDate.timezoneHr = -14;
+ tempDate.timezoneMin = 0;
+ tempDate.utc='-';
+ normalize(tempDate);
+ c2 = compareOrder(date1, tempDate);
+ if (c2 == GREATER_THAN)
+ return c2;
+
+ return INDETERMINATE;
+ }
+ else if ( date2.utc=='Z' ) {
+
+ //compare (date1 with time zone -14)<=date2
+ //
+ cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate
+ tempDate.timezoneHr = -14;
+ tempDate.timezoneMin = 0;
+ tempDate.utc='-';
+ if (DEBUG) {
+ System.out.println("tempDate=" + dateToString(tempDate));
+ }
+ normalize(tempDate);
+ c1 = compareOrder(tempDate, date2);
+ if (DEBUG) {
+ System.out.println("date=" + dateToString(date2));
+ System.out.println("tempDate=" + dateToString(tempDate));
+ }
+ if (c1 == LESS_THAN)
+ return c1;
+
+ //compare (date1 with time zone +14)<=date2
+ //
+ cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate
+ tempDate.timezoneHr = 14;
+ tempDate.timezoneMin = 0;
+ tempDate.utc='+';
+ normalize(tempDate);
+ c2 = compareOrder(tempDate, date2);
+ if (DEBUG) {
+ System.out.println("tempDate=" + dateToString(tempDate));
+ }
+ if (c2 == GREATER_THAN)
+ return c2;
+
+ return INDETERMINATE;
+ }
+ return INDETERMINATE;
+
+ }
+
+ /**
+ * Given normalized values, determines order-relation
+ * between give date/time objects.
+ *
+ * @param date1 date/time object
+ * @param date2 date/time object
+ * @return 0 if date1 and date2 are equal, a value less than 0 if date1 is less than date2, a value greater than 0 if date1 is greater than date2
+ */
+ protected short compareOrder(DateTimeData date1, DateTimeData date2) {
+ if(date1.position < 1) {
+ if (date1.year < date2.year)
+ return -1;
+ if (date1.year > date2.year)
+ return 1;
+ }
+ if(date1.position < 2) {
+ if (date1.month < date2.month)
+ return -1;
+ if (date1.month > date2.month)
+ return 1;
+ }
+ if (date1.day < date2.day)
+ return -1;
+ if (date1.day > date2.day)
+ return 1;
+ if (date1.hour < date2.hour)
+ return -1;
+ if (date1.hour > date2.hour)
+ return 1;
+ if (date1.minute < date2.minute)
+ return -1;
+ if (date1.minute > date2.minute)
+ return 1;
+ if (date1.second < date2.second)
+ return -1;
+ if (date1.second > date2.second)
+ return 1;
+ if (date1.utc < date2.utc)
+ return -1;
+ if (date1.utc > date2.utc)
+ return 1;
+ return 0;
+ }
+
+ /**
+ * Parses time hh:mm:ss.sss and time zone if any
+ *
+ * @param start
+ * @param end
+ * @param data
+ * @exception RuntimeException
+ */
+ protected void getTime (String buffer, int start, int end, DateTimeData data) throws RuntimeException{
+
+ int stop = start+2;
+
+ //get hours (hh)
+ data.hour=parseInt(buffer, start,stop);
+
+ //get minutes (mm)
+
+ if (buffer.charAt(stop++)!=':') {
+ throw new RuntimeException("Error in parsing time zone" );
+ }
+ start = stop;
+ stop = stop+2;
+ data.minute=parseInt(buffer, start,stop);
+
+ //get seconds (ss)
+ if (buffer.charAt(stop++)!=':') {
+ throw new RuntimeException("Error in parsing time zone" );
+ }
+
+ //find UTC sign if any
+ int sign = findUTCSign(buffer, start, end);
+
+ //get seconds (ms)
+ start = stop;
+ stop = sign < 0 ? end : sign;
+ data.second = parseSecond(buffer, start, stop);
+
+ //parse UTC time zone (hh:mm)
+ if (sign > 0) {
+ getTimeZone(buffer, data, sign, end);
+ }
+ }
+
+ /**
+ * Parses date CCYY-MM-DD
+ *
+ * @param buffer
+ * @param start start position
+ * @param end end position
+ * @param date
+ * @exception RuntimeException
+ */
+ protected int getDate (String buffer, int start, int end, DateTimeData date) throws RuntimeException{
+
+ start = getYearMonth(buffer, start, end, date);
+
+ if (buffer.charAt(start++) !='-') {
+ throw new RuntimeException("CCYY-MM must be followed by '-' sign");
+ }
+ int stop = start + 2;
+ date.day=parseInt(buffer, start, stop);
+ return stop;
+ }
+
+ /**
+ * Parses date CCYY-MM
+ *
+ * @param buffer
+ * @param start start position
+ * @param end end position
+ * @param date
+ * @exception RuntimeException
+ */
+ protected int getYearMonth (String buffer, int start, int end, DateTimeData date) throws RuntimeException{
+
+ if ( buffer.charAt(0)=='-' ) {
+ // REVISIT: date starts with preceding '-' sign
+ // do we have to do anything with it?
+ //
+ start++;
+ }
+ int i = indexOf(buffer, start, end, '-');
+ if ( i==-1 ) throw new RuntimeException("Year separator is missing or misplaced");
+ int length = i-start;
+ if (length<4) {
+ throw new RuntimeException("Year must have 'CCYY' format");
+ }
+ else if (length > 4 && buffer.charAt(start)=='0'){
+ throw new RuntimeException("Leading zeros are required if the year value would otherwise have fewer than four digits; otherwise they are forbidden");
+ }
+ date.year= parseIntYear(buffer, i);
+ if (buffer.charAt(i)!='-') {
+ throw new RuntimeException("CCYY must be followed by '-' sign");
+ }
+ start = ++i;
+ i = start +2;
+ date.month=parseInt(buffer, start, i);
+ return i; //fStart points right after the MONTH
+ }
+
+ /**
+ * Shared code from Date and YearMonth datatypes.
+ * Finds if time zone sign is present
+ *
+ * @param end
+ * @param date
+ * @exception RuntimeException
+ */
+ protected void parseTimeZone (String buffer, int start, int end, DateTimeData date) throws RuntimeException{
+
+ //fStart points right after the date
+
+ if ( start < end ) {
+ if (!isNextCharUTCSign(buffer, start, end)) {
+ throw new RuntimeException ("Error in month parsing");
+ }
+ else {
+ getTimeZone(buffer, date, start, end);
+ }
+ }
+ }
+
+ /**
+ * Parses time zone: 'Z' or {+,-} followed by hh:mm
+ *
+ * @param data
+ * @param sign
+ * @exception RuntimeException
+ */
+ protected void getTimeZone (String buffer, DateTimeData data, int sign, int end) throws RuntimeException{
+ data.utc=buffer.charAt(sign);
+
+ if ( buffer.charAt(sign) == 'Z' ) {
+ if (end>(++sign)) {
+ throw new RuntimeException("Error in parsing time zone");
+ }
+ return;
+ }
+ if ( sign<=(end-6) ) {
+
+ int negate = buffer.charAt(sign) == '-'?-1:1;
+ //parse hr
+ int stop = ++sign+2;
+ data.timezoneHr = negate*parseInt(buffer, sign, stop);
+ if (buffer.charAt(stop++)!=':') {
+ throw new RuntimeException("Error in parsing time zone" );
+ }
+
+ //parse min
+ data.timezoneMin = negate*parseInt(buffer, stop, stop+2);
+
+ if ( stop+2!=end ) {
+ throw new RuntimeException("Error in parsing time zone");
+ }
+ if(data.timezoneHr != 0 || data.timezoneMin != 0)
+ data.normalized = false;
+ }
+ else {
+ throw new RuntimeException("Error in parsing time zone");
+ }
+ if ( DEBUG ) {
+ System.out.println("time[hh]="+data.timezoneHr + " time[mm]=" +data.timezoneMin);
+ }
+ }
+
+ /**
+ * Computes index of given char within StringBuffer
+ *
+ * @param start
+ * @param end
+ * @param ch character to look for in StringBuffer
+ * @return index of ch within StringBuffer
+ */
+ protected int indexOf (String buffer, int start, int end, char ch) {
+ for ( int i=start;i12 ) {
+ throw new RuntimeException("The month must have values 1 to 12");
+
+ }
+
+ //validate days
+ if ( data.day>maxDayInMonthFor(data.year, data.month) || data.day<1 ) {
+ throw new RuntimeException("The day must have values 1 to 31");
+ }
+
+ //validate hours
+ if ( data.hour>23 || data.hour<0 ) {
+ if (data.hour == 24 && data.minute == 0 && data.second == 0) {
+ data.hour = 0;
+ if (++data.day > maxDayInMonthFor(data.year, data.month)) {
+ data.day = 1;
+ if (++data.month > 12) {
+ data.month = 1;
+ if (Constants.SCHEMA_1_1_SUPPORT) {
+ ++data.year;
+ }
+ else if (++data.year == 0) {
+ data.year = 1;
+ }
+ }
+ }
+ }
+ else {
+ throw new RuntimeException("Hour must have values 0-23, unless 24:00:00");
+ }
+ }
+
+ //validate
+ if ( data.minute>59 || data.minute<0 ) {
+ throw new RuntimeException("Minute must have values 0-59");
+ }
+
+ //validate
+ if ( data.second>=60 || data.second<0 ) {
+ throw new RuntimeException("Second must have values 0-59");
+
+ }
+
+ //validate
+ if ( data.timezoneHr>14 || data.timezoneHr<-14 ) {
+ throw new RuntimeException("Time zone should have range -14:00 to +14:00");
+ }
+ else {
+ if((data.timezoneHr == 14 || data.timezoneHr == -14) && data.timezoneMin != 0)
+ throw new RuntimeException("Time zone should have range -14:00 to +14:00");
+ else if(data.timezoneMin > 59 || data.timezoneMin < -59)
+ throw new RuntimeException("Minute must have values 0-59");
+ }
+
+ }
+
+ /**
+ * Return index of UTC char: 'Z', '+', '-'
+ *
+ * @param start
+ * @param end
+ * @return index of the UTC character that was found
+ */
+ protected int findUTCSign (String buffer, int start, int end) {
+ int c;
+ for ( int i=start;itrue if the character at start is 'Z', '+' or '-'.
+ */
+ protected final boolean isNextCharUTCSign(String buffer, int start, int end) {
+ if (start < end) {
+ char c = buffer.charAt(start);
+ return (c == 'Z' || c == '+' || c == '-');
+ }
+ return false;
+ }
+
+ /**
+ * Given start and end position, parses string value
+ *
+ * @param buffer string to parse
+ * @param start start position
+ * @param end end position
+ * @return return integer representation of characters
+ */
+ protected int parseInt (String buffer, int start, int end)
+ throws NumberFormatException{
+ //REVISIT: more testing on this parsing needs to be done.
+ int radix=10;
+ int result = 0;
+ int digit=0;
+ int limit = -Integer.MAX_VALUE;
+ int multmin = limit / radix;
+ int i = start;
+ do {
+ digit = getDigit(buffer.charAt(i));
+ if ( digit < 0 ) throw new NumberFormatException("'" + buffer + "' has wrong format");
+ if ( result < multmin ) throw new NumberFormatException("'" + buffer + "' has wrong format");
+ result *= radix;
+ if ( result < limit + digit ) throw new NumberFormatException("'" + buffer + "' has wrong format");
+ result -= digit;
+
+ }while ( ++i < end );
+ return -result;
+ }
+
+ // parse Year differently to support negative value.
+ protected int parseIntYear (String buffer, int end){
+ int radix=10;
+ int result = 0;
+ boolean negative = false;
+ int i=0;
+ int limit;
+ int multmin;
+ int digit=0;
+
+ if (buffer.charAt(0) == '-'){
+ negative = true;
+ limit = Integer.MIN_VALUE;
+ i++;
+
+ }
+ else{
+ limit = -Integer.MAX_VALUE;
+ }
+ multmin = limit / radix;
+ while (i < end)
+ {
+ digit = getDigit(buffer.charAt(i++));
+ if (digit < 0) throw new NumberFormatException("'" + buffer + "' has wrong format");
+ if (result < multmin) throw new NumberFormatException("'" + buffer + "' has wrong format");
+ result *= radix;
+ if (result < limit + digit) throw new NumberFormatException("'" + buffer + "' has wrong format");
+ result -= digit;
+ }
+
+ if (negative)
+ {
+ if (i > 1) return result;
+ else throw new NumberFormatException("'" + buffer + "' has wrong format");
+ }
+ return -result;
+
+ }
+
+ /**
+ * If timezone present - normalize dateTime [E Adding durations to dateTimes]
+ *
+ * @param date CCYY-MM-DDThh:mm:ss+03
+ */
+ protected void normalize(DateTimeData date) {
+
+ // REVISIT: we have common code in addDuration() for durations
+ // should consider reorganizing it.
+ //
+
+ //add minutes (from time zone)
+ int negate = -1;
+
+ if ( DEBUG ) {
+ System.out.println("==>date.minute"+date.minute);
+ System.out.println("==>date.timezoneMin" +date.timezoneMin);
+ }
+ int temp = date.minute + negate * date.timezoneMin;
+ int carry = fQuotient (temp, 60);
+ date.minute= mod(temp, 60, carry);
+
+ if ( DEBUG ) {
+ System.out.println("==>carry: " + carry);
+ }
+ //add hours
+ temp = date.hour + negate * date.timezoneHr + carry;
+ carry = fQuotient(temp, 24);
+ date.hour=mod(temp, 24, carry);
+ if ( DEBUG ) {
+ System.out.println("==>date.hour"+date.hour);
+ System.out.println("==>carry: " + carry);
+ }
+
+ date.day=date.day+carry;
+
+ while ( true ) {
+ temp=maxDayInMonthFor(date.year, date.month);
+ if (date.day<1) {
+ date.day = date.day + maxDayInMonthFor(date.year, date.month-1);
+ carry=-1;
+ }
+ else if ( date.day>temp ) {
+ date.day=date.day-temp;
+ carry=1;
+ }
+ else {
+ break;
+ }
+ temp=date.month+carry;
+ date.month=modulo(temp, 1, 13);
+ date.year=date.year+fQuotient(temp, 1, 13);
+ if(date.year == 0 && !Constants.SCHEMA_1_1_SUPPORT) {
+ date.year = (date.timezoneHr < 0 || date.timezoneMin < 0)?1:-1;
+ }
+ }
+ date.utc='Z';
+ }
+
+
+ /**
+ * @param date
+ */
+ protected void saveUnnormalized(DateTimeData date) {
+ date.unNormYear = date.year;
+ date.unNormMonth = date.month;
+ date.unNormDay = date.day;
+ date.unNormHour = date.hour;
+ date.unNormMinute = date.minute;
+ date.unNormSecond = date.second;
+ }
+
+ /**
+ * Resets object representation of date/time
+ *
+ * @param data date/time object
+ */
+ protected void resetDateObj(DateTimeData data) {
+ data.year = 0;
+ data.month = 0;
+ data.day = 0;
+ data.hour = 0;
+ data.minute = 0;
+ data.second = 0;
+ data.utc = 0;
+ data.timezoneHr = 0;
+ data.timezoneMin = 0;
+ }
+
+ /**
+ * Given {year,month} computes maximum
+ * number of days for given month
+ *
+ * @param year
+ * @param month
+ * @return integer containg the number of days in a given month
+ */
+ protected int maxDayInMonthFor(int year, int month) {
+ //validate days
+ if ( month==4 || month==6 || month==9 || month==11 ) {
+ return 30;
+ }
+ else if ( month==2 ) {
+ if ( isLeapYear(year) ) {
+ return 29;
+ }
+ else {
+ return 28;
+ }
+ }
+ else {
+ return 31;
+ }
+ }
+
+ private boolean isLeapYear(int year) {
+
+ //REVISIT: should we take care about Julian calendar?
+ return((year%4 == 0) && ((year%100 != 0) || (year%400 == 0)));
+ }
+
+ //
+ // help function described in W3C PR Schema [E Adding durations to dateTimes]
+ //
+ protected int mod (int a, int b, int quotient) {
+ //modulo(a, b) = a - fQuotient(a,b)*b
+ return (a - quotient*b) ;
+ }
+
+ //
+ // help function described in W3C PR Schema [E Adding durations to dateTimes]
+ //
+ protected int fQuotient (int a, int b) {
+
+ //fQuotient(a, b) = the greatest integer less than or equal to a/b
+ return (int)Math.floor((float)a/b);
+ }
+
+ //
+ // help function described in W3C PR Schema [E Adding durations to dateTimes]
+ //
+ protected int modulo (int temp, int low, int high) {
+ //modulo(a - low, high - low) + low
+ int a = temp - low;
+ int b = high - low;
+ return (mod (a, b, fQuotient(a, b)) + low) ;
+ }
+
+ //
+ // help function described in W3C PR Schema [E Adding durations to dateTimes]
+ //
+ protected int fQuotient (int temp, int low, int high) {
+ //fQuotient(a - low, high - low)
+
+ return fQuotient(temp - low, high - low);
+ }
+
+
+ protected String dateToString(DateTimeData date) {
+ StringBuffer message = new StringBuffer(25);
+ append(message, date.year, 4);
+ message.append('-');
+ append(message, date.month, 2);
+ message.append('-');
+ append(message, date.day, 2);
+ message.append('T');
+ append(message, date.hour, 2);
+ message.append(':');
+ append(message, date.minute, 2);
+ message.append(':');
+ append(message, date.second);
+ append(message, (char)date.utc, 0);
+ return message.toString();
+ }
+
+ protected final void append(StringBuffer message, int value, int nch) {
+ if (value == Integer.MIN_VALUE) {
+ message.append(value);
+ return;
+ }
+ if (value < 0) {
+ message.append('-');
+ value = -value;
+ }
+ if (nch == 4) {
+ if (value < 10)
+ message.append("000");
+ else if (value < 100)
+ message.append("00");
+ else if (value < 1000)
+ message.append('0');
+ message.append(value);
+ }
+ else if (nch == 2) {
+ if (value < 10)
+ message.append('0');
+ message.append(value);
+ }
+ else {
+ if (value != 0)
+ message.append((char)value);
+ }
+ }
+
+ protected final void append(StringBuffer message, double value) {
+ if (value < 0) {
+ message.append('-');
+ value = -value;
+ }
+ if (value < 10) {
+ message.append('0');
+ }
+ append2(message, value);
+ }
+
+ protected final void append2(StringBuffer message, double value) {
+ final int intValue = (int) value;
+ if (value == intValue) {
+ message.append(intValue);
+ }
+ else {
+ append3(message, value);
+ }
+ }
+
+ private void append3(StringBuffer message, double value) {
+ String d = String.valueOf(value);
+ int eIndex = d.indexOf('E');
+ if (eIndex == -1) {
+ message.append(d);
+ return;
+ }
+ int exp;
+ if (value < 1) {
+ // Need to convert from scientific notation of the form
+ // n.nnn...E-N (N >= 4) to a normal decimal value.
+ try {
+ exp = parseInt(d, eIndex+2, d.length());
+ }
+ // This should never happen.
+ // It's only possible if String.valueOf(double) is broken.
+ catch (Exception e) {
+ message.append(d);
+ return;
+ }
+ message.append("0.");
+ for (int i = 1; i < exp; ++i) {
+ message.append('0');
+ }
+ // Remove trailing zeros.
+ int end = eIndex - 1;
+ while (end > 0) {
+ char c = d.charAt(end);
+ if (c != '0') {
+ break;
+ }
+ --end;
+ }
+ // Now append the digits to the end. Skip over the decimal point.
+ for (int i = 0; i <= end; ++i) {
+ char c = d.charAt(i);
+ if (c != '.') {
+ message.append(c);
+ }
+ }
+ }
+ else {
+ // Need to convert from scientific notation of the form
+ // n.nnn...EN (N >= 7) to a normal decimal value.
+ try {
+ exp = parseInt(d, eIndex+1, d.length());
+ }
+ // This should never happen.
+ // It's only possible if String.valueOf(double) is broken.
+ catch (Exception e) {
+ message.append(d);
+ return;
+ }
+ final int integerEnd = exp + 2;
+ for (int i = 0; i < eIndex; ++i) {
+ char c = d.charAt(i);
+ if (c != '.') {
+ if (i == integerEnd) {
+ message.append('.');
+ }
+ message.append(c);
+ }
+ }
+ // Append trailing zeroes if necessary.
+ for (int i = integerEnd - eIndex; i > 0; --i) {
+ message.append('0');
+ }
+ }
+ }
+
+ protected double parseSecond(String buffer, int start, int end)
+ throws NumberFormatException {
+ int dot = -1;
+ for (int i = start; i < end; i++) {
+ char ch = buffer.charAt(i);
+ if (ch == '.')
+ dot = i;
+ else if (ch > '9' || ch < '0')
+ throw new NumberFormatException("'" + buffer + "' has wrong format");
+ }
+ if (dot == -1) {
+ if (start+2 != end)
+ throw new NumberFormatException("'" + buffer + "' has wrong format");
+ }
+ else if (start+2 != dot || dot+1 == end) {
+ throw new NumberFormatException("'" + buffer + "' has wrong format");
+ }
+ return Double.parseDouble(buffer.substring(start, end));
+ }
+
+ //
+ //Private help functions
+ //
+
+ private void cloneDate (DateTimeData finalValue, DateTimeData tempDate) {
+ tempDate.year = finalValue.year;
+ tempDate.month = finalValue.month;
+ tempDate.day = finalValue.day;
+ tempDate.hour = finalValue.hour;
+ tempDate.minute = finalValue.minute;
+ tempDate.second = finalValue.second;
+ tempDate.utc = finalValue.utc;
+ tempDate.timezoneHr = finalValue.timezoneHr;
+ tempDate.timezoneMin = finalValue.timezoneMin;
+ }
+
+ /**
+ * Represents date time data
+ */
+ static final class DateTimeData implements XSDateTime {
+ int year, month, day, hour, minute, utc;
+ double second;
+ int timezoneHr, timezoneMin;
+ private String originalValue;
+ boolean normalized = true;
+
+ int unNormYear;
+ int unNormMonth;
+ int unNormDay;
+ int unNormHour;
+ int unNormMinute;
+ double unNormSecond;
+
+ // used for comparisons - to decide the 'interesting' portions of
+ // a date/time based data type.
+ int position;
+ // a pointer to the type that was used go generate this data
+ // note that this is not the actual simple type, but one of the
+ // statically created XXXDV objects, so this won't cause any GC problem.
+ final AbstractDateTimeDV type;
+ private String canonical;
+ public DateTimeData(String originalValue, AbstractDateTimeDV type) {
+ this.originalValue = originalValue;
+ this.type = type;
+ }
+ public DateTimeData(int year, int month, int day, int hour, int minute,
+ double second, int utc, String originalValue, boolean normalized, AbstractDateTimeDV type) {
+ this.year = year;
+ this.month = month;
+ this.day = day;
+ this.hour = hour;
+ this.minute = minute;
+ this.second = second;
+ this.utc = utc;
+ this.type = type;
+ this.originalValue = originalValue;
+ }
+ public boolean equals(Object obj) {
+ if (!(obj instanceof DateTimeData))
+ return false;
+ return type.compareDates(this, (DateTimeData)obj, true)==0;
+ }
+ public synchronized String toString() {
+ if (canonical == null) {
+ canonical = type.dateToString(this);
+ }
+ return canonical;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#getYear()
+ */
+ public int getYears() {
+ if(type instanceof DurationDV)
+ return 0;
+ return normalized?year:unNormYear;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#getMonth()
+ */
+ public int getMonths() {
+ if(type instanceof DurationDV) {
+ return year*12 + month;
+ }
+ return normalized?month:unNormMonth;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#getDay()
+ */
+ public int getDays() {
+ if(type instanceof DurationDV)
+ return 0;
+ return normalized?day:unNormDay;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#getHour()
+ */
+ public int getHours() {
+ if(type instanceof DurationDV)
+ return 0;
+ return normalized?hour:unNormHour;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#getMinutes()
+ */
+ public int getMinutes() {
+ if(type instanceof DurationDV)
+ return 0;
+ return normalized?minute:unNormMinute;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#getSeconds()
+ */
+ public double getSeconds() {
+ if(type instanceof DurationDV) {
+ return day*24*60*60 + hour*60*60 + minute*60 + second;
+ }
+ return normalized?second:unNormSecond;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#hasTimeZone()
+ */
+ public boolean hasTimeZone() {
+ return utc != 0;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneHours()
+ */
+ public int getTimeZoneHours() {
+ return timezoneHr;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneMinutes()
+ */
+ public int getTimeZoneMinutes() {
+ return timezoneMin;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#getLexicalValue()
+ */
+ public String getLexicalValue() {
+ return originalValue;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#normalize()
+ */
+ public XSDateTime normalize() {
+ if(!normalized) {
+ DateTimeData dt = (DateTimeData)this.clone();
+ dt.normalized = true;
+ return dt;
+ }
+ return this;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#isNormalized()
+ */
+ public boolean isNormalized() {
+ return normalized;
+ }
+
+ public Object clone() {
+ DateTimeData dt = new DateTimeData(this.year, this.month, this.day, this.hour,
+ this.minute, this.second, this.utc, this.originalValue, this.normalized, this.type);
+ dt.canonical = this.canonical;
+ dt.position = position;
+ dt.timezoneHr = this.timezoneHr;
+ dt.timezoneMin = this.timezoneMin;
+ dt.unNormYear = this.unNormYear;
+ dt.unNormMonth = this.unNormMonth;
+ dt.unNormDay = this.unNormDay;
+ dt.unNormHour = this.unNormHour;
+ dt.unNormMinute = this.unNormMinute;
+ dt.unNormSecond = this.unNormSecond;
+ return dt;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#getXMLGregorianCalendar()
+ */
+ public XMLGregorianCalendar getXMLGregorianCalendar() {
+ return type.getXMLGregorianCalendar(this);
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.datatypes.XSDateTime#getDuration()
+ */
+ public Duration getDuration() {
+ return type.getDuration(this);
+ }
+ }
+
+ protected XMLGregorianCalendar getXMLGregorianCalendar(DateTimeData data) {
+ return null;
+ }
+
+ protected Duration getDuration(DateTimeData data) {
+ return null;
+ }
+
+ protected final BigDecimal getFractionalSecondsAsBigDecimal(DateTimeData data) {
+ final StringBuffer buf = new StringBuffer();
+ append3(buf, data.unNormSecond);
+ String value = buf.toString();
+ final int index = value.indexOf('.');
+ if (index == -1) {
+ return null;
+ }
+ value = value.substring(index);
+ final BigDecimal _val = new BigDecimal(value);
+ if (_val.compareTo(BigDecimal.valueOf(0)) == 0) {
+ return null;
+ }
+ return _val;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/AnyAtomicDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/AnyAtomicDV.java
new file mode 100644
index 0000000..7e9bbeb
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/AnyAtomicDV.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Represent the schema type "anyAtomicType"
+ *
+ * @xerces.experimental
+ *
+ * @author Ankit Pasricha, IBM
+ *
+ * @version $Id$
+ */
+class AnyAtomicDV extends TypeValidator {
+
+ public short getAllowedFacets() {
+ return 0;
+ }
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ return content;
+ }
+
+} // class AnyAtomicDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/AnySimpleDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/AnySimpleDV.java
new file mode 100644
index 0000000..a805db4
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/AnySimpleDV.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Represent the schema type "anySimpleType"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class AnySimpleDV extends TypeValidator {
+
+ public short getAllowedFacets() {
+ // anySimpleType doesn't allow any facet, not even whiteSpace
+ return 0;
+ }
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ return content;
+ }
+
+} // class AnySimpleDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/AnyURIDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/AnyURIDV.java
new file mode 100644
index 0000000..31534fa
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/AnyURIDV.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.URI;
+
+/**
+ * Represent the schema type "anyURI"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class AnyURIDV extends TypeValidator {
+
+ private static final URI BASE_URI;
+ static {
+ URI uri = null;
+ try {
+ uri = new URI("abc://def.ghi.jkl");
+ } catch (URI.MalformedURIException ex) {
+ }
+ BASE_URI = uri;
+ }
+
+ public short getAllowedFacets(){
+ return (XSSimpleTypeDecl.FACET_LENGTH | XSSimpleTypeDecl.FACET_MINLENGTH | XSSimpleTypeDecl.FACET_MAXLENGTH | XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_ENUMERATION | XSSimpleTypeDecl.FACET_WHITESPACE );
+ }
+
+ // before we return string we have to make sure it is correct URI as per spec.
+ // for some types (string and derived), they just return the string itself
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ // check 3.2.17.c0 must: URI (rfc 2396/2723)
+ try {
+ if( content.length() != 0 ) {
+ // encode special characters using XLink 5.4 algorithm
+ final String encoded = encode(content);
+ // Support for relative URLs
+ // According to Java 1.1: URLs may also be specified with a
+ // String and the URL object that it is related to.
+ new URI(BASE_URI, encoded );
+ }
+ } catch (URI.MalformedURIException ex) {
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "anyURI"});
+ }
+
+ // REVISIT: do we need to return the new URI object?
+ return content;
+ }
+
+ // which ASCII characters need to be escaped
+ private static boolean gNeedEscaping[] = new boolean[128];
+ // the first hex character if a character needs to be escaped
+ private static char gAfterEscaping1[] = new char[128];
+ // the second hex character if a character needs to be escaped
+ private static char gAfterEscaping2[] = new char[128];
+ private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+ // initialize the above 3 arrays
+ static {
+ for (int i = 0; i <= 0x1f; i++) {
+ gNeedEscaping[i] = true;
+ gAfterEscaping1[i] = gHexChs[i >> 4];
+ gAfterEscaping2[i] = gHexChs[i & 0xf];
+ }
+ gNeedEscaping[0x7f] = true;
+ gAfterEscaping1[0x7f] = '7';
+ gAfterEscaping2[0x7f] = 'F';
+ char[] escChs = {' ', '<', '>', '"', '{', '}',
+ '|', '\\', '^', '~', '`'};
+ int len = escChs.length;
+ char ch;
+ for (int i = 0; i < len; i++) {
+ ch = escChs[i];
+ gNeedEscaping[ch] = true;
+ gAfterEscaping1[ch] = gHexChs[ch >> 4];
+ gAfterEscaping2[ch] = gHexChs[ch & 0xf];
+ }
+ }
+
+ // To encode special characters in anyURI, by using %HH to represent
+ // special ASCII characters: 0x00~0x1F, 0x7F, ' ', '<', '>', etc.
+ // and non-ASCII characters (whose value >= 128).
+ private static String encode(String anyURI){
+ int len = anyURI.length(), ch;
+ StringBuffer buffer = new StringBuffer(len*3);
+
+ // for each character in the anyURI
+ int i = 0;
+ for (; i < len; i++) {
+ ch = anyURI.charAt(i);
+ // if it's not an ASCII character, break here, and use UTF-8 encoding
+ if (ch >= 128)
+ break;
+ if (gNeedEscaping[ch]) {
+ buffer.append('%');
+ buffer.append(gAfterEscaping1[ch]);
+ buffer.append(gAfterEscaping2[ch]);
+ }
+ else {
+ buffer.append((char)ch);
+ }
+ }
+
+ // we saw some non-ascii character
+ if (i < len) {
+ // get UTF-8 bytes for the remaining sub-string
+ byte[] bytes = null;
+ byte b;
+ try {
+ bytes = anyURI.substring(i).getBytes("UTF-8");
+ } catch (java.io.UnsupportedEncodingException e) {
+ // should never happen
+ return anyURI;
+ }
+ len = bytes.length;
+
+ // for each byte
+ for (i = 0; i < len; i++) {
+ b = bytes[i];
+ // for non-ascii character: make it positive, then escape
+ if (b < 0) {
+ ch = b + 256;
+ buffer.append('%');
+ buffer.append(gHexChs[ch >> 4]);
+ buffer.append(gHexChs[ch & 0xf]);
+ }
+ else if (gNeedEscaping[b]) {
+ buffer.append('%');
+ buffer.append(gAfterEscaping1[b]);
+ buffer.append(gAfterEscaping2[b]);
+ }
+ else {
+ buffer.append((char)b);
+ }
+ }
+ }
+
+ // If encoding happened, create a new string;
+ // otherwise, return the orginal one.
+ if (buffer.length() != len) {
+ return buffer.toString();
+ }
+ else {
+ return anyURI;
+ }
+ }
+
+} // class AnyURIDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/Base64BinaryDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/Base64BinaryDV.java
new file mode 100644
index 0000000..274320e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/Base64BinaryDV.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.impl.dv.util.Base64;
+import org.apache.xerces.impl.dv.util.ByteListImpl;
+
+/**
+ * Represent the schema type "base64Binary"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class Base64BinaryDV extends TypeValidator {
+
+ public short getAllowedFacets(){
+ return (XSSimpleTypeDecl.FACET_LENGTH | XSSimpleTypeDecl.FACET_MINLENGTH | XSSimpleTypeDecl.FACET_MAXLENGTH | XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_ENUMERATION | XSSimpleTypeDecl.FACET_WHITESPACE );
+ }
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ byte[] decoded = Base64.decode(content);
+ if (decoded == null)
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "base64Binary"});
+
+ return new XBase64(decoded);
+ }
+
+ // length of a binary type is the number of bytes
+ public int getDataLength(Object value) {
+ return ((XBase64)value).getLength();
+ }
+
+ /**
+ * represent base64 data
+ */
+ private static final class XBase64 extends ByteListImpl {
+
+ public XBase64(byte[] data) {
+ super(data);
+ }
+ public synchronized String toString() {
+ if (canonical == null) {
+ canonical = Base64.encode(data);
+ }
+ return canonical;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof XBase64))
+ return false;
+ byte[] odata = ((XBase64)obj).data;
+ int len = data.length;
+ if (len != odata.length)
+ return false;
+ for (int i = 0; i < len; i++) {
+ if (data[i] != odata[i])
+ return false;
+ }
+ return true;
+ }
+
+ public int hashCode() {
+ int hash = 0;
+ for (int i = 0; i < data.length; ++i) {
+ hash = hash * 37 + (((int) data[i]) & 0xff);
+ }
+ return hash;
+ }
+ }
+} // class Base64BinaryDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/BaseDVFactory.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/BaseDVFactory.java
new file mode 100644
index 0000000..43754c2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/BaseDVFactory.java
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.SchemaDVFactory;
+import org.apache.xerces.impl.dv.XSFacets;
+import org.apache.xerces.impl.dv.XSSimpleType;
+import org.apache.xerces.util.SymbolHash;
+import org.apache.xerces.xs.XSConstants;
+import org.apache.xerces.xs.XSObjectList;
+
+/**
+ * the factory to create/return built-in schema DVs and create user-defined DVs
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class BaseDVFactory extends SchemaDVFactory {
+
+ static final String URI_SCHEMAFORSCHEMA = "http://www.w3.org/2001/XMLSchema";
+
+ // there are 27 types. 53 is the closest prime number to 27*2=54.
+ static SymbolHash fBaseTypes = new SymbolHash(53);
+ static {
+ createBuiltInTypes(fBaseTypes);
+ }
+
+ /**
+ * Get a built-in simple type of the given name
+ * REVISIT: its still not decided within the Schema WG how to define the
+ * ur-types and if all simple types should be derived from a
+ * complex type, so as of now we ignore the fact that anySimpleType
+ * is derived from anyType, and pass 'null' as the base of
+ * anySimpleType. It needs to be changed as per the decision taken.
+ *
+ * @param name the name of the datatype
+ * @return the datatype validator of the given name
+ */
+ public XSSimpleType getBuiltInType(String name) {
+ return (XSSimpleType)fBaseTypes.get(name);
+ }
+
+ /**
+ * get all built-in simple types, which are stored in a hashtable keyed by
+ * the name
+ *
+ * @return a hashtable which contains all built-in simple types
+ */
+ public SymbolHash getBuiltInTypes() {
+ return (SymbolHash)fBaseTypes.makeClone();
+ }
+
+ /**
+ * Create a new simple type which is derived by restriction from another
+ * simple type.
+ *
+ * @param name name of the new type, could be null
+ * @param targetNamespace target namespace of the new type, could be null
+ * @param finalSet value of "final"
+ * @param base base type of the new type
+ * @param annotations set of annotations
+ * @return the newly created simple type
+ */
+ public XSSimpleType createTypeRestriction(String name, String targetNamespace,
+ short finalSet, XSSimpleType base, XSObjectList annotations) {
+ return new XSSimpleTypeDecl((XSSimpleTypeDecl)base, name, targetNamespace, finalSet, false, annotations);
+ }
+
+ /**
+ * Create a new simple type which is derived by list from another simple
+ * type.
+ *
+ * @param name name of the new type, could be null
+ * @param targetNamespace target namespace of the new type, could be null
+ * @param finalSet value of "final"
+ * @param itemType item type of the list type
+ * @param annotations set of annotations
+ * @return the newly created simple type
+ */
+ public XSSimpleType createTypeList(String name, String targetNamespace,
+ short finalSet, XSSimpleType itemType,
+ XSObjectList annotations) {
+ return new XSSimpleTypeDecl(name, targetNamespace, finalSet, (XSSimpleTypeDecl)itemType, false, annotations);
+ }
+
+ /**
+ * Create a new simple type which is derived by union from a list of other
+ * simple types.
+ *
+ * @param name name of the new type, could be null
+ * @param targetNamespace target namespace of the new type, could be null
+ * @param finalSet value of "final"
+ * @param memberTypes member types of the union type
+ * @param annotations set of annotations
+ * @return the newly created simple type
+ */
+ public XSSimpleType createTypeUnion(String name, String targetNamespace,
+ short finalSet, XSSimpleType[] memberTypes,
+ XSObjectList annotations) {
+ int typeNum = memberTypes.length;
+ XSSimpleTypeDecl[] mtypes = new XSSimpleTypeDecl[typeNum];
+ System.arraycopy(memberTypes, 0, mtypes, 0, typeNum);
+
+ return new XSSimpleTypeDecl(name, targetNamespace, finalSet, mtypes, annotations);
+ }
+
+ // create all built-in types
+ static void createBuiltInTypes(SymbolHash types) {
+ // base schema simple type names
+ final String ANYSIMPLETYPE = "anySimpleType";
+ final String ANYURI = "anyURI";
+ final String BASE64BINARY = "base64Binary";
+ final String BOOLEAN = "boolean";
+ final String BYTE = "byte";
+ final String DATE = "date";
+ final String DATETIME = "dateTime";
+ final String DAY = "gDay";
+ final String DECIMAL = "decimal";
+ final String INT = "int";
+ final String INTEGER = "integer";
+ final String LONG = "long";
+ final String NEGATIVEINTEGER = "negativeInteger";
+ final String MONTH = "gMonth";
+ final String MONTHDAY = "gMonthDay";
+ final String NONNEGATIVEINTEGER= "nonNegativeInteger";
+ final String NONPOSITIVEINTEGER= "nonPositiveInteger";
+ final String POSITIVEINTEGER = "positiveInteger";
+ final String SHORT = "short";
+ final String STRING = "string";
+ final String TIME = "time";
+ final String UNSIGNEDBYTE = "unsignedByte";
+ final String UNSIGNEDINT = "unsignedInt";
+ final String UNSIGNEDLONG = "unsignedLong";
+ final String UNSIGNEDSHORT = "unsignedShort";
+ final String YEAR = "gYear";
+ final String YEARMONTH = "gYearMonth";
+
+ final XSFacets facets = new XSFacets();
+
+ XSSimpleTypeDecl anySimpleType = XSSimpleTypeDecl.fAnySimpleType;
+ types.put(ANYSIMPLETYPE, anySimpleType);
+ XSSimpleTypeDecl stringDV = new XSSimpleTypeDecl(anySimpleType, STRING, XSSimpleTypeDecl.DV_STRING, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.STRING_DT);
+ types.put(STRING, stringDV);
+ types.put(BOOLEAN, new XSSimpleTypeDecl(anySimpleType, BOOLEAN, XSSimpleTypeDecl.DV_BOOLEAN, XSSimpleType.ORDERED_FALSE, false, true, false, true, XSConstants.BOOLEAN_DT));
+ XSSimpleTypeDecl decimalDV = new XSSimpleTypeDecl(anySimpleType, DECIMAL, XSSimpleTypeDecl.DV_DECIMAL, XSSimpleType.ORDERED_TOTAL, false, false, true, true, XSConstants.DECIMAL_DT);
+ types.put(DECIMAL, decimalDV);
+
+ types.put(ANYURI, new XSSimpleTypeDecl(anySimpleType, ANYURI, XSSimpleTypeDecl.DV_ANYURI, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.ANYURI_DT));
+ types.put(BASE64BINARY, new XSSimpleTypeDecl(anySimpleType, BASE64BINARY, XSSimpleTypeDecl.DV_BASE64BINARY, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.BASE64BINARY_DT));
+ types.put(DATETIME, new XSSimpleTypeDecl(anySimpleType, DATETIME, XSSimpleTypeDecl.DV_DATETIME, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.DATETIME_DT));
+ types.put(TIME, new XSSimpleTypeDecl(anySimpleType, TIME, XSSimpleTypeDecl.DV_TIME, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.TIME_DT));
+ types.put(DATE, new XSSimpleTypeDecl(anySimpleType, DATE, XSSimpleTypeDecl.DV_DATE, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.DATE_DT));
+ types.put(YEARMONTH, new XSSimpleTypeDecl(anySimpleType, YEARMONTH, XSSimpleTypeDecl.DV_GYEARMONTH, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.GYEARMONTH_DT));
+ types.put(YEAR, new XSSimpleTypeDecl(anySimpleType, YEAR, XSSimpleTypeDecl.DV_GYEAR, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.GYEAR_DT));
+ types.put(MONTHDAY, new XSSimpleTypeDecl(anySimpleType, MONTHDAY, XSSimpleTypeDecl.DV_GMONTHDAY, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.GMONTHDAY_DT));
+ types.put(DAY, new XSSimpleTypeDecl(anySimpleType, DAY, XSSimpleTypeDecl.DV_GDAY, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.GDAY_DT));
+ types.put(MONTH, new XSSimpleTypeDecl(anySimpleType, MONTH, XSSimpleTypeDecl.DV_GMONTH, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.GMONTH_DT));
+
+ XSSimpleTypeDecl integerDV = new XSSimpleTypeDecl(decimalDV, INTEGER, XSSimpleTypeDecl.DV_INTEGER, XSSimpleType.ORDERED_TOTAL, false, false, true, true, XSConstants.INTEGER_DT);
+ types.put(INTEGER, integerDV);
+
+ facets.maxInclusive = "0";
+ XSSimpleTypeDecl nonPositiveDV = new XSSimpleTypeDecl(integerDV, NONPOSITIVEINTEGER, URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NONPOSITIVEINTEGER_DT);
+ nonPositiveDV.applyFacets1(facets , XSSimpleType.FACET_MAXINCLUSIVE, (short)0);
+ types.put(NONPOSITIVEINTEGER, nonPositiveDV);
+
+ facets.maxInclusive = "-1";
+ XSSimpleTypeDecl negativeDV = new XSSimpleTypeDecl(nonPositiveDV, NEGATIVEINTEGER, URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NEGATIVEINTEGER_DT);
+ negativeDV.applyFacets1(facets , XSSimpleType.FACET_MAXINCLUSIVE, (short)0);
+ types.put(NEGATIVEINTEGER, negativeDV);
+
+ facets.maxInclusive = "9223372036854775807";
+ facets.minInclusive = "-9223372036854775808";
+ XSSimpleTypeDecl longDV = new XSSimpleTypeDecl(integerDV, LONG, URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.LONG_DT);
+ longDV.applyFacets1(facets , (short)(XSSimpleType.FACET_MAXINCLUSIVE | XSSimpleType.FACET_MININCLUSIVE), (short)0 );
+ types.put(LONG, longDV);
+
+
+ facets.maxInclusive = "2147483647";
+ facets.minInclusive = "-2147483648";
+ XSSimpleTypeDecl intDV = new XSSimpleTypeDecl(longDV, INT, URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.INT_DT);
+ intDV.applyFacets1(facets, (short)(XSSimpleType.FACET_MAXINCLUSIVE | XSSimpleType.FACET_MININCLUSIVE), (short)0 );
+ types.put(INT, intDV);
+
+ facets.maxInclusive = "32767";
+ facets.minInclusive = "-32768";
+ XSSimpleTypeDecl shortDV = new XSSimpleTypeDecl(intDV, SHORT , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.SHORT_DT);
+ shortDV.applyFacets1(facets, (short)(XSSimpleType.FACET_MAXINCLUSIVE | XSSimpleType.FACET_MININCLUSIVE), (short)0 );
+ types.put(SHORT, shortDV);
+
+ facets.maxInclusive = "127";
+ facets.minInclusive = "-128";
+ XSSimpleTypeDecl byteDV = new XSSimpleTypeDecl(shortDV, BYTE , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.BYTE_DT);
+ byteDV.applyFacets1(facets, (short)(XSSimpleType.FACET_MAXINCLUSIVE | XSSimpleType.FACET_MININCLUSIVE), (short)0 );
+ types.put(BYTE, byteDV);
+
+ facets.minInclusive = "0" ;
+ XSSimpleTypeDecl nonNegativeDV = new XSSimpleTypeDecl(integerDV, NONNEGATIVEINTEGER , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NONNEGATIVEINTEGER_DT);
+ nonNegativeDV.applyFacets1(facets, XSSimpleType.FACET_MININCLUSIVE, (short)0 );
+ types.put(NONNEGATIVEINTEGER, nonNegativeDV);
+
+ facets.maxInclusive = "18446744073709551615" ;
+ XSSimpleTypeDecl unsignedLongDV = new XSSimpleTypeDecl(nonNegativeDV, UNSIGNEDLONG , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.UNSIGNEDLONG_DT);
+ unsignedLongDV.applyFacets1(facets, XSSimpleType.FACET_MAXINCLUSIVE, (short)0 );
+ types.put(UNSIGNEDLONG, unsignedLongDV);
+
+ facets.maxInclusive = "4294967295" ;
+ XSSimpleTypeDecl unsignedIntDV = new XSSimpleTypeDecl(unsignedLongDV, UNSIGNEDINT , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.UNSIGNEDINT_DT);
+ unsignedIntDV.applyFacets1(facets, XSSimpleType.FACET_MAXINCLUSIVE, (short)0 );
+ types.put(UNSIGNEDINT, unsignedIntDV);
+
+ facets.maxInclusive = "65535" ;
+ XSSimpleTypeDecl unsignedShortDV = new XSSimpleTypeDecl(unsignedIntDV, UNSIGNEDSHORT , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.UNSIGNEDSHORT_DT);
+ unsignedShortDV.applyFacets1(facets, XSSimpleType.FACET_MAXINCLUSIVE, (short)0 );
+ types.put(UNSIGNEDSHORT, unsignedShortDV);
+
+ facets.maxInclusive = "255" ;
+ XSSimpleTypeDecl unsignedByteDV = new XSSimpleTypeDecl(unsignedShortDV, UNSIGNEDBYTE , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.UNSIGNEDBYTE_DT);
+ unsignedByteDV.applyFacets1(facets, XSSimpleType.FACET_MAXINCLUSIVE, (short)0 );
+ types.put(UNSIGNEDBYTE, unsignedByteDV);
+
+ facets.minInclusive = "1" ;
+ XSSimpleTypeDecl positiveIntegerDV = new XSSimpleTypeDecl(nonNegativeDV, POSITIVEINTEGER , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.POSITIVEINTEGER_DT);
+ positiveIntegerDV.applyFacets1(facets, XSSimpleType.FACET_MININCLUSIVE, (short)0 );
+ types.put(POSITIVEINTEGER, positiveIntegerDV);
+ }//createBuiltInTypes(SymbolHash)
+
+}//BaseDVFactory
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/BaseSchemaDVFactory.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/BaseSchemaDVFactory.java
new file mode 100644
index 0000000..5627ba3
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/BaseSchemaDVFactory.java
@@ -0,0 +1,325 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.SchemaDVFactory;
+import org.apache.xerces.impl.dv.XSFacets;
+import org.apache.xerces.impl.dv.XSSimpleType;
+import org.apache.xerces.impl.xs.XSDeclarationPool;
+import org.apache.xerces.util.SymbolHash;
+import org.apache.xerces.xs.XSConstants;
+import org.apache.xerces.xs.XSObjectList;
+
+/**
+ * the base factory to create/return built-in schema DVs and create user-defined DVs
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ * @author Khaled Noaman, IBM
+ *
+ * @version $Id$
+ */
+public abstract class BaseSchemaDVFactory extends SchemaDVFactory {
+
+ static final String URI_SCHEMAFORSCHEMA = "http://www.w3.org/2001/XMLSchema";
+
+ protected XSDeclarationPool fDeclPool = null;
+
+ // create common built-in types
+ protected static void createBuiltInTypes(SymbolHash builtInTypes, XSSimpleTypeDecl baseAtomicType) {
+ // all schema simple type names
+ final String ANYSIMPLETYPE = "anySimpleType";
+ final String ANYURI = "anyURI";
+ final String BASE64BINARY = "base64Binary";
+ final String BOOLEAN = "boolean";
+ final String BYTE = "byte";
+ final String DATE = "date";
+ final String DATETIME = "dateTime";
+ final String DAY = "gDay";
+ final String DECIMAL = "decimal";
+ final String DOUBLE = "double";
+ final String DURATION = "duration";
+ final String ENTITY = "ENTITY";
+ final String ENTITIES = "ENTITIES";
+ final String FLOAT = "float";
+ final String HEXBINARY = "hexBinary";
+ final String ID = "ID";
+ final String IDREF = "IDREF";
+ final String IDREFS = "IDREFS";
+ final String INT = "int";
+ final String INTEGER = "integer";
+ final String LONG = "long";
+ final String NAME = "Name";
+ final String NEGATIVEINTEGER = "negativeInteger";
+ final String MONTH = "gMonth";
+ final String MONTHDAY = "gMonthDay";
+ final String NCNAME = "NCName";
+ final String NMTOKEN = "NMTOKEN";
+ final String NMTOKENS = "NMTOKENS";
+ final String LANGUAGE = "language";
+ final String NONNEGATIVEINTEGER= "nonNegativeInteger";
+ final String NONPOSITIVEINTEGER= "nonPositiveInteger";
+ final String NORMALIZEDSTRING = "normalizedString";
+ final String NOTATION = "NOTATION";
+ final String POSITIVEINTEGER = "positiveInteger";
+ final String QNAME = "QName";
+ final String SHORT = "short";
+ final String STRING = "string";
+ final String TIME = "time";
+ final String TOKEN = "token";
+ final String UNSIGNEDBYTE = "unsignedByte";
+ final String UNSIGNEDINT = "unsignedInt";
+ final String UNSIGNEDLONG = "unsignedLong";
+ final String UNSIGNEDSHORT = "unsignedShort";
+ final String YEAR = "gYear";
+ final String YEARMONTH = "gYearMonth";
+
+ final XSFacets facets = new XSFacets();
+
+ builtInTypes.put(ANYSIMPLETYPE, XSSimpleTypeDecl.fAnySimpleType);
+
+ XSSimpleTypeDecl stringDV = new XSSimpleTypeDecl(baseAtomicType, STRING, XSSimpleTypeDecl.DV_STRING, XSSimpleType.ORDERED_FALSE, false, false, false , true, XSConstants.STRING_DT);
+ builtInTypes.put(STRING, stringDV);
+ builtInTypes.put(BOOLEAN, new XSSimpleTypeDecl(baseAtomicType, BOOLEAN, XSSimpleTypeDecl.DV_BOOLEAN, XSSimpleType.ORDERED_FALSE, false, true, false, true, XSConstants.BOOLEAN_DT));
+ XSSimpleTypeDecl decimalDV = new XSSimpleTypeDecl(baseAtomicType, DECIMAL, XSSimpleTypeDecl.DV_DECIMAL, XSSimpleType.ORDERED_TOTAL, false, false, true, true, XSConstants.DECIMAL_DT);
+ builtInTypes.put(DECIMAL, decimalDV);
+
+ builtInTypes.put(ANYURI, new XSSimpleTypeDecl(baseAtomicType, ANYURI, XSSimpleTypeDecl.DV_ANYURI, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.ANYURI_DT));
+ builtInTypes.put(BASE64BINARY, new XSSimpleTypeDecl(baseAtomicType, BASE64BINARY, XSSimpleTypeDecl.DV_BASE64BINARY, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.BASE64BINARY_DT));
+
+ XSSimpleTypeDecl durationDV = new XSSimpleTypeDecl(baseAtomicType, DURATION, XSSimpleTypeDecl.DV_DURATION, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.DURATION_DT);
+ builtInTypes.put(DURATION, durationDV);
+
+ builtInTypes.put(DATETIME, new XSSimpleTypeDecl(baseAtomicType, DATETIME, XSSimpleTypeDecl.DV_DATETIME, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.DATETIME_DT));
+ builtInTypes.put(TIME, new XSSimpleTypeDecl(baseAtomicType, TIME, XSSimpleTypeDecl.DV_TIME, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.TIME_DT));
+ builtInTypes.put(DATE, new XSSimpleTypeDecl(baseAtomicType, DATE, XSSimpleTypeDecl.DV_DATE, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.DATE_DT));
+ builtInTypes.put(YEARMONTH, new XSSimpleTypeDecl(baseAtomicType, YEARMONTH, XSSimpleTypeDecl.DV_GYEARMONTH, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.GYEARMONTH_DT));
+ builtInTypes.put(YEAR, new XSSimpleTypeDecl(baseAtomicType, YEAR, XSSimpleTypeDecl.DV_GYEAR, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.GYEAR_DT));
+ builtInTypes.put(MONTHDAY, new XSSimpleTypeDecl(baseAtomicType, MONTHDAY, XSSimpleTypeDecl.DV_GMONTHDAY, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.GMONTHDAY_DT));
+ builtInTypes.put(DAY, new XSSimpleTypeDecl(baseAtomicType, DAY, XSSimpleTypeDecl.DV_GDAY, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.GDAY_DT));
+ builtInTypes.put(MONTH, new XSSimpleTypeDecl(baseAtomicType, MONTH, XSSimpleTypeDecl.DV_GMONTH, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.GMONTH_DT));
+
+ XSSimpleTypeDecl integerDV = new XSSimpleTypeDecl(decimalDV, INTEGER, XSSimpleTypeDecl.DV_INTEGER, XSSimpleType.ORDERED_TOTAL, false, false, true, true, XSConstants.INTEGER_DT);
+ builtInTypes.put(INTEGER, integerDV);
+
+ facets.maxInclusive = "0";
+ XSSimpleTypeDecl nonPositiveDV = new XSSimpleTypeDecl(integerDV, NONPOSITIVEINTEGER, URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NONPOSITIVEINTEGER_DT);
+ nonPositiveDV.applyFacets1(facets , XSSimpleType.FACET_MAXINCLUSIVE, (short)0);
+ builtInTypes.put(NONPOSITIVEINTEGER, nonPositiveDV);
+
+ facets.maxInclusive = "-1";
+ XSSimpleTypeDecl negativeDV = new XSSimpleTypeDecl(nonPositiveDV, NEGATIVEINTEGER, URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NEGATIVEINTEGER_DT);
+ negativeDV.applyFacets1(facets , XSSimpleType.FACET_MAXINCLUSIVE, (short)0);
+ builtInTypes.put(NEGATIVEINTEGER, negativeDV);
+
+ facets.maxInclusive = "9223372036854775807";
+ facets.minInclusive = "-9223372036854775808";
+ XSSimpleTypeDecl longDV = new XSSimpleTypeDecl(integerDV, LONG, URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.LONG_DT);
+ longDV.applyFacets1(facets , (short)(XSSimpleType.FACET_MAXINCLUSIVE | XSSimpleType.FACET_MININCLUSIVE), (short)0 );
+ builtInTypes.put(LONG, longDV);
+
+ facets.maxInclusive = "2147483647";
+ facets.minInclusive = "-2147483648";
+ XSSimpleTypeDecl intDV = new XSSimpleTypeDecl(longDV, INT, URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.INT_DT);
+ intDV.applyFacets1(facets, (short)(XSSimpleType.FACET_MAXINCLUSIVE | XSSimpleType.FACET_MININCLUSIVE), (short)0 );
+ builtInTypes.put(INT, intDV);
+
+ facets.maxInclusive = "32767";
+ facets.minInclusive = "-32768";
+ XSSimpleTypeDecl shortDV = new XSSimpleTypeDecl(intDV, SHORT , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.SHORT_DT);
+ shortDV.applyFacets1(facets, (short)(XSSimpleType.FACET_MAXINCLUSIVE | XSSimpleType.FACET_MININCLUSIVE), (short)0 );
+ builtInTypes.put(SHORT, shortDV);
+
+ facets.maxInclusive = "127";
+ facets.minInclusive = "-128";
+ XSSimpleTypeDecl byteDV = new XSSimpleTypeDecl(shortDV, BYTE , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.BYTE_DT);
+ byteDV.applyFacets1(facets, (short)(XSSimpleType.FACET_MAXINCLUSIVE | XSSimpleType.FACET_MININCLUSIVE), (short)0 );
+ builtInTypes.put(BYTE, byteDV);
+
+ facets.minInclusive = "0" ;
+ XSSimpleTypeDecl nonNegativeDV = new XSSimpleTypeDecl(integerDV, NONNEGATIVEINTEGER , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NONNEGATIVEINTEGER_DT);
+ nonNegativeDV.applyFacets1(facets, XSSimpleType.FACET_MININCLUSIVE, (short)0 );
+ builtInTypes.put(NONNEGATIVEINTEGER, nonNegativeDV);
+
+ facets.maxInclusive = "18446744073709551615" ;
+ XSSimpleTypeDecl unsignedLongDV = new XSSimpleTypeDecl(nonNegativeDV, UNSIGNEDLONG , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.UNSIGNEDLONG_DT);
+ unsignedLongDV.applyFacets1(facets, XSSimpleType.FACET_MAXINCLUSIVE, (short)0 );
+ builtInTypes.put(UNSIGNEDLONG, unsignedLongDV);
+
+ facets.maxInclusive = "4294967295" ;
+ XSSimpleTypeDecl unsignedIntDV = new XSSimpleTypeDecl(unsignedLongDV, UNSIGNEDINT , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.UNSIGNEDINT_DT);
+ unsignedIntDV.applyFacets1(facets, XSSimpleType.FACET_MAXINCLUSIVE, (short)0 );
+ builtInTypes.put(UNSIGNEDINT, unsignedIntDV);
+
+ facets.maxInclusive = "65535" ;
+ XSSimpleTypeDecl unsignedShortDV = new XSSimpleTypeDecl(unsignedIntDV, UNSIGNEDSHORT , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.UNSIGNEDSHORT_DT);
+ unsignedShortDV.applyFacets1(facets, XSSimpleType.FACET_MAXINCLUSIVE, (short)0 );
+ builtInTypes.put(UNSIGNEDSHORT, unsignedShortDV);
+
+ facets.maxInclusive = "255" ;
+ XSSimpleTypeDecl unsignedByteDV = new XSSimpleTypeDecl(unsignedShortDV, UNSIGNEDBYTE , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.UNSIGNEDBYTE_DT);
+ unsignedByteDV.applyFacets1(facets, XSSimpleType.FACET_MAXINCLUSIVE, (short)0 );
+ builtInTypes.put(UNSIGNEDBYTE, unsignedByteDV);
+
+ facets.minInclusive = "1" ;
+ XSSimpleTypeDecl positiveIntegerDV = new XSSimpleTypeDecl(nonNegativeDV, POSITIVEINTEGER , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.POSITIVEINTEGER_DT);
+ positiveIntegerDV.applyFacets1(facets, XSSimpleType.FACET_MININCLUSIVE, (short)0 );
+ builtInTypes.put(POSITIVEINTEGER, positiveIntegerDV);
+
+ builtInTypes.put(FLOAT, new XSSimpleTypeDecl(baseAtomicType, FLOAT, XSSimpleTypeDecl.DV_FLOAT, XSSimpleType.ORDERED_PARTIAL, true, true, true, true, XSConstants.FLOAT_DT));
+ builtInTypes.put(DOUBLE, new XSSimpleTypeDecl(baseAtomicType, DOUBLE, XSSimpleTypeDecl.DV_DOUBLE, XSSimpleType.ORDERED_PARTIAL, true, true, true, true, XSConstants.DOUBLE_DT));
+ builtInTypes.put(HEXBINARY, new XSSimpleTypeDecl(baseAtomicType, HEXBINARY, XSSimpleTypeDecl.DV_HEXBINARY, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.HEXBINARY_DT));
+ builtInTypes.put(NOTATION, new XSSimpleTypeDecl(baseAtomicType, NOTATION, XSSimpleTypeDecl.DV_NOTATION, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.NOTATION_DT));
+
+ facets.whiteSpace = XSSimpleType.WS_REPLACE;
+ XSSimpleTypeDecl normalizedDV = new XSSimpleTypeDecl(stringDV, NORMALIZEDSTRING , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NORMALIZEDSTRING_DT);
+ normalizedDV.applyFacets1(facets, XSSimpleType.FACET_WHITESPACE, (short)0 );
+ builtInTypes.put(NORMALIZEDSTRING, normalizedDV);
+
+ facets.whiteSpace = XSSimpleType.WS_COLLAPSE;
+ XSSimpleTypeDecl tokenDV = new XSSimpleTypeDecl(normalizedDV, TOKEN , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.TOKEN_DT);
+ tokenDV.applyFacets1(facets, XSSimpleType.FACET_WHITESPACE, (short)0 );
+ builtInTypes.put(TOKEN, tokenDV);
+
+ facets.whiteSpace = XSSimpleType.WS_COLLAPSE;
+ facets.pattern = "([a-zA-Z]{1,8})(-[a-zA-Z0-9]{1,8})*";
+ XSSimpleTypeDecl languageDV = new XSSimpleTypeDecl(tokenDV, LANGUAGE , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.LANGUAGE_DT);
+ languageDV.applyFacets1(facets, (short)(XSSimpleType.FACET_WHITESPACE | XSSimpleType.FACET_PATTERN) ,(short)0);
+ builtInTypes.put(LANGUAGE, languageDV);
+
+ facets.whiteSpace = XSSimpleType.WS_COLLAPSE;
+ XSSimpleTypeDecl nameDV = new XSSimpleTypeDecl(tokenDV, NAME , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NAME_DT);
+ nameDV.applyFacets1(facets, XSSimpleType.FACET_WHITESPACE, (short)0, XSSimpleTypeDecl.SPECIAL_PATTERN_NAME);
+ builtInTypes.put(NAME, nameDV);
+
+ facets.whiteSpace = XSSimpleType.WS_COLLAPSE;
+ XSSimpleTypeDecl ncnameDV = new XSSimpleTypeDecl(nameDV, NCNAME , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NCNAME_DT) ;
+ ncnameDV.applyFacets1(facets, XSSimpleType.FACET_WHITESPACE, (short)0, XSSimpleTypeDecl.SPECIAL_PATTERN_NCNAME);
+ builtInTypes.put(NCNAME, ncnameDV);
+
+ builtInTypes.put(QNAME, new XSSimpleTypeDecl(baseAtomicType, QNAME, XSSimpleTypeDecl.DV_QNAME, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.QNAME_DT));
+
+ builtInTypes.put(ID, new XSSimpleTypeDecl(ncnameDV, ID, XSSimpleTypeDecl.DV_ID, XSSimpleType.ORDERED_FALSE, false, false, false , true, XSConstants.ID_DT));
+ XSSimpleTypeDecl idrefDV = new XSSimpleTypeDecl(ncnameDV, IDREF , XSSimpleTypeDecl.DV_IDREF, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.IDREF_DT);
+ builtInTypes.put(IDREF, idrefDV);
+
+ facets.minLength = 1;
+ XSSimpleTypeDecl tempDV = new XSSimpleTypeDecl(null, URI_SCHEMAFORSCHEMA, (short)0, idrefDV, true, null);
+ XSSimpleTypeDecl idrefsDV = new XSSimpleTypeDecl(tempDV, IDREFS, URI_SCHEMAFORSCHEMA, (short)0, false, null);
+ idrefsDV.applyFacets1(facets, XSSimpleType.FACET_MINLENGTH, (short)0);
+ builtInTypes.put(IDREFS, idrefsDV);
+
+ XSSimpleTypeDecl entityDV = new XSSimpleTypeDecl(ncnameDV, ENTITY , XSSimpleTypeDecl.DV_ENTITY, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.ENTITY_DT);
+ builtInTypes.put(ENTITY, entityDV);
+
+ facets.minLength = 1;
+ tempDV = new XSSimpleTypeDecl(null, URI_SCHEMAFORSCHEMA, (short)0, entityDV, true, null);
+ XSSimpleTypeDecl entitiesDV = new XSSimpleTypeDecl(tempDV, ENTITIES, URI_SCHEMAFORSCHEMA, (short)0, false, null);
+ entitiesDV.applyFacets1(facets, XSSimpleType.FACET_MINLENGTH, (short)0);
+ builtInTypes.put(ENTITIES, entitiesDV);
+
+ facets.whiteSpace = XSSimpleType.WS_COLLAPSE;
+ XSSimpleTypeDecl nmtokenDV = new XSSimpleTypeDecl(tokenDV, NMTOKEN, URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NMTOKEN_DT);
+ nmtokenDV.applyFacets1(facets, XSSimpleType.FACET_WHITESPACE, (short)0, XSSimpleTypeDecl.SPECIAL_PATTERN_NMTOKEN);
+ builtInTypes.put(NMTOKEN, nmtokenDV);
+
+ facets.minLength = 1;
+ tempDV = new XSSimpleTypeDecl(null, URI_SCHEMAFORSCHEMA, (short)0, nmtokenDV, true, null);
+ XSSimpleTypeDecl nmtokensDV = new XSSimpleTypeDecl(tempDV, NMTOKENS, URI_SCHEMAFORSCHEMA, (short)0, false, null);
+ nmtokensDV.applyFacets1(facets, XSSimpleType.FACET_MINLENGTH, (short)0);
+ builtInTypes.put(NMTOKENS, nmtokensDV);
+ } //createBuiltInTypes()
+
+ /**
+ * Create a new simple type which is derived by restriction from another
+ * simple type.
+ *
+ * @param name name of the new type, could be null
+ * @param targetNamespace target namespace of the new type, could be null
+ * @param finalSet value of "final"
+ * @param base base type of the new type
+ * @param annotations set of annotations
+ * @return the newly created simple type
+ */
+ public XSSimpleType createTypeRestriction(String name, String targetNamespace,
+ short finalSet, XSSimpleType base, XSObjectList annotations) {
+
+ if (fDeclPool != null) {
+ XSSimpleTypeDecl st= fDeclPool.getSimpleTypeDecl();
+ return st.setRestrictionValues((XSSimpleTypeDecl)base, name, targetNamespace, finalSet, annotations);
+ }
+ return new XSSimpleTypeDecl((XSSimpleTypeDecl)base, name, targetNamespace, finalSet, false, annotations);
+ }
+
+ /**
+ * Create a new simple type which is derived by list from another simple
+ * type.
+ *
+ * @param name name of the new type, could be null
+ * @param targetNamespace target namespace of the new type, could be null
+ * @param finalSet value of "final"
+ * @param itemType item type of the list type
+ * @param annotations set of annotations
+ * @return the newly created simple type
+ */
+ public XSSimpleType createTypeList(String name, String targetNamespace,
+ short finalSet, XSSimpleType itemType,
+ XSObjectList annotations) {
+ if (fDeclPool != null) {
+ XSSimpleTypeDecl st= fDeclPool.getSimpleTypeDecl();
+ return st.setListValues(name, targetNamespace, finalSet, (XSSimpleTypeDecl)itemType, annotations);
+ }
+ return new XSSimpleTypeDecl(name, targetNamespace, finalSet, (XSSimpleTypeDecl)itemType, false, annotations);
+ }
+
+ /**
+ * Create a new simple type which is derived by union from a list of other
+ * simple types.
+ *
+ * @param name name of the new type, could be null
+ * @param targetNamespace target namespace of the new type, could be null
+ * @param finalSet value of "final"
+ * @param memberTypes member types of the union type
+ * @param annotations set of annotations
+ * @return the newly created simple type
+ */
+ public XSSimpleType createTypeUnion(String name, String targetNamespace,
+ short finalSet, XSSimpleType[] memberTypes,
+ XSObjectList annotations) {
+ int typeNum = memberTypes.length;
+ XSSimpleTypeDecl[] mtypes = new XSSimpleTypeDecl[typeNum];
+ System.arraycopy(memberTypes, 0, mtypes, 0, typeNum);
+
+ if (fDeclPool != null) {
+ XSSimpleTypeDecl st= fDeclPool.getSimpleTypeDecl();
+ return st.setUnionValues(name, targetNamespace, finalSet, mtypes, annotations);
+ }
+ return new XSSimpleTypeDecl(name, targetNamespace, finalSet, mtypes, annotations);
+ }
+
+ public void setDeclPool (XSDeclarationPool declPool){
+ fDeclPool = declPool;
+ }
+
+ /** Implementation internal **/
+ public XSSimpleTypeDecl newXSSimpleTypeDecl() {
+ return new XSSimpleTypeDecl();
+ }
+} //BaseSchemaDVFactory
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/BooleanDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/BooleanDV.java
new file mode 100644
index 0000000..56fdc96
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/BooleanDV.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Represent the schema type "boolean"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class BooleanDV extends TypeValidator {
+
+ public short getAllowedFacets() {
+ return (XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE);
+ }
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ if ("false".equals(content) || "0".equals(content)) {
+ return Boolean.FALSE;
+ }
+ else if ("true".equals(content) || "1".equals(content)) {
+ return Boolean.TRUE;
+ }
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "boolean"});
+ }
+
+} // class BooleanDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DateDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DateDV.java
new file mode 100644
index 0000000..abe1d9b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DateDV.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Validator for datatype (W3C Schema datatypes)
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani
+ * @author Gopal Sharma, SUN Microsystems Inc.
+ *
+ * @version $Id$
+ */
+public class DateDV extends DateTimeDV {
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ try{
+ return parse(content);
+ } catch(Exception ex){
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "date"});
+ }
+ }
+
+ /**
+ * Parses, validates and computes normalized version of dateTime object
+ *
+ * @param str The lexical representation of dateTime object CCYY-MM-DD
+ * with possible time zone Z or (-),(+)hh:mm
+ * @return normalized dateTime representation
+ * @exception SchemaDateTimeException Invalid lexical representation
+ */
+ protected DateTimeData parse(String str) throws SchemaDateTimeException {
+ DateTimeData date = new DateTimeData(str, this);
+ int len = str.length();
+
+ int end = getDate(str, 0, len, date);
+ parseTimeZone (str, end, len, date);
+
+ //validate and normalize
+ //REVISIT: do we need SchemaDateTimeException?
+ validateDateTime(date);
+
+ //save unnormalized values
+ saveUnnormalized(date);
+
+ if (date.utc!=0 && date.utc!='Z') {
+ normalize(date);
+ }
+ return date;
+ }
+
+ protected String dateToString(DateTimeData date) {
+ StringBuffer message = new StringBuffer(25);
+ append(message, date.year, 4);
+ message.append('-');
+ append(message, date.month, 2);
+ message.append('-');
+ append(message, date.day, 2);
+ append(message, (char)date.utc, 0);
+ return message.toString();
+ }
+
+ protected XMLGregorianCalendar getXMLGregorianCalendar(DateTimeData date) {
+ return datatypeFactory.newXMLGregorianCalendar(date.unNormYear, date.unNormMonth,
+ date.unNormDay, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED,
+ DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED,
+ date.hasTimeZone() ? (date.timezoneHr * 60 + date.timezoneMin) : DatatypeConstants.FIELD_UNDEFINED);
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DateTimeDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DateTimeDV.java
new file mode 100644
index 0000000..fe739f8
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DateTimeDV.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import java.math.BigInteger;
+
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Validator for <dateTime> datatype (W3C Schema Datatypes)
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani
+ * @author Gopal Sharma, SUN Microsystem Inc.
+ *
+ * @version $Id$
+ */
+public class DateTimeDV extends AbstractDateTimeDV {
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ try{
+ return parse(content);
+ } catch(Exception ex){
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "dateTime"});
+ }
+ }
+
+ /**
+ * Parses, validates and computes normalized version of dateTime object
+ *
+ * @param str The lexical representation of dateTime object CCYY-MM-DDThh:mm:ss.sss
+ * with possible time zone Z or (-),(+)hh:mm
+ * @return normalized dateTime representation
+ * @exception SchemaDateTimeException Invalid lexical representation
+ */
+ protected DateTimeData parse(String str) throws SchemaDateTimeException {
+ DateTimeData date = new DateTimeData(str, this);
+ int len = str.length();
+
+ int end = indexOf (str, 0, len, 'T');
+
+ // both time and date
+ int dateEnd = getDate(str, 0, end, date);
+ getTime(str, end+1, len, date);
+
+ //Check the separator character between Date and Time
+ if (dateEnd != end) {
+ throw new RuntimeException(str
+ + " is an invalid dateTime dataype value. "
+ + "Invalid character(s) seprating date and time values.");
+ }
+
+ //validate and normalize
+
+ //REVISIT: do we need SchemaDateTimeException?
+ validateDateTime(date);
+
+ //save unnormalized values
+ saveUnnormalized(date);
+
+ if (date.utc!=0 && date.utc!='Z') {
+ normalize(date);
+ }
+ return date;
+ }
+
+ protected XMLGregorianCalendar getXMLGregorianCalendar(DateTimeData date) {
+ return datatypeFactory.newXMLGregorianCalendar(BigInteger.valueOf(date.unNormYear), date.unNormMonth,
+ date.unNormDay, date.unNormHour, date.unNormMinute,
+ (int)date.unNormSecond, date.unNormSecond != 0 ? getFractionalSecondsAsBigDecimal(date) : null,
+ date.hasTimeZone() ? (date.timezoneHr * 60 + date.timezoneMin) : DatatypeConstants.FIELD_UNDEFINED);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DayDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DayDV.java
new file mode 100644
index 0000000..c2073ae
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DayDV.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Validator for <gDay> datatype (W3C Schema datatypes)
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani
+ * @author Gopal Sharma, SUN Microsystem Inc.
+ * @version $Id$
+ */
+public class DayDV extends AbstractDateTimeDV {
+
+ //size without time zone: ---09
+ private final static int DAY_SIZE=5;
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ try{
+ return parse(content);
+ } catch(Exception ex){
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "gDay"});
+ }
+ }
+
+ /**
+ * Parses, validates and computes normalized version of gDay object
+ *
+ * @param str The lexical representation of gDay object ---DD
+ * with possible time zone Z or (-),(+)hh:mm
+ * Pattern: ---(\\d\\d)(Z|(([-+])(\\d\\d)(:(\\d\\d))?
+ * @return normalized date representation
+ * @exception SchemaDateTimeException Invalid lexical representation
+ */
+ protected DateTimeData parse(String str) throws SchemaDateTimeException {
+ DateTimeData date = new DateTimeData(str, this);
+ int len = str.length();
+
+ if (str.charAt(0)!='-' || str.charAt(1)!='-' || str.charAt(2)!='-') {
+ throw new SchemaDateTimeException ("Error in day parsing");
+ }
+
+ //initialize values
+ date.year=YEAR;
+ date.month=MONTH;
+
+ date.day=parseInt(str, 3,5);
+
+ if ( DAY_SIZE type
+ *
+ * @xerces.internal
+ *
+ * @author Ankit Pasricha, IBM
+ *
+ * @version $Id$
+ */
+class DayTimeDurationDV extends DurationDV {
+
+ public Object getActualValue(String content, ValidationContext context)
+ throws InvalidDatatypeValueException {
+ try {
+ return parse(content, DurationDV.DAYTIMEDURATION_TYPE);
+ }
+ catch (Exception ex) {
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "dayTimeDuration"});
+ }
+ }
+
+ protected Duration getDuration(DateTimeData date) {
+ int sign = 1;
+ if (date.day<0 || date.hour<0 || date.minute<0 || date.second<0) {
+ sign = -1;
+ }
+ return datatypeFactory.newDuration(sign == 1, null, null,
+ date.day != DatatypeConstants.FIELD_UNDEFINED?BigInteger.valueOf(sign*date.day):null,
+ date.hour != DatatypeConstants.FIELD_UNDEFINED?BigInteger.valueOf(sign*date.hour):null,
+ date.minute != DatatypeConstants.FIELD_UNDEFINED?BigInteger.valueOf(sign*date.minute):null,
+ date.second != DatatypeConstants.FIELD_UNDEFINED?new BigDecimal(String.valueOf(sign*date.second)):null);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DecimalDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DecimalDV.java
new file mode 100644
index 0000000..32685f0
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DecimalDV.java
@@ -0,0 +1,362 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.xs.datatypes.XSDecimal;
+
+/**
+ * Represent the schema type "decimal"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class DecimalDV extends TypeValidator {
+
+ public final short getAllowedFacets(){
+ return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE | XSSimpleTypeDecl.FACET_TOTALDIGITS | XSSimpleTypeDecl.FACET_FRACTIONDIGITS);
+ }
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ try {
+ return new XDecimal(content);
+ } catch (NumberFormatException nfe) {
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "decimal"});
+ }
+ }
+
+ public final int compare(Object value1, Object value2){
+ return ((XDecimal)value1).compareTo((XDecimal)value2);
+ }
+
+ public final int getTotalDigits(Object value){
+ return ((XDecimal)value).totalDigits;
+ }
+
+ public final int getFractionDigits(Object value){
+ return ((XDecimal)value).fracDigits;
+ }
+
+ // Avoid using the heavy-weight java.math.BigDecimal
+ static class XDecimal implements XSDecimal {
+ // sign: 0 for vlaue 0; 1 for positive values; -1 for negative values
+ int sign = 1;
+ // total digits. >= 1
+ int totalDigits = 0;
+ // integer digits when sign != 0
+ int intDigits = 0;
+ // fraction digits when sign != 0
+ int fracDigits = 0;
+ // the string representing the integer part
+ String ivalue = "";
+ // the string representing the fraction part
+ String fvalue = "";
+ // whether the canonical form contains decimal point
+ boolean integer = false;
+
+ XDecimal(String content) throws NumberFormatException {
+ initD(content);
+ }
+ XDecimal(String content, boolean integer) throws NumberFormatException {
+ if (integer)
+ initI(content);
+ else
+ initD(content);
+ }
+ void initD(String content) throws NumberFormatException {
+ int len = content.length();
+ if (len == 0)
+ throw new NumberFormatException();
+
+ // these 4 variables are used to indicate where the integre/fraction
+ // parts start/end.
+ int intStart = 0, intEnd = 0, fracStart = 0, fracEnd = 0;
+
+ // Deal with leading sign symbol if present
+ if (content.charAt(0) == '+') {
+ // skip '+', so intStart should be 1
+ intStart = 1;
+ }
+ else if (content.charAt(0) == '-') {
+ // keep '-', so intStart is stil 0
+ intStart = 1;
+ sign = -1;
+ }
+
+ // skip leading zeroes in integer part
+ int actualIntStart = intStart;
+ while (actualIntStart < len && content.charAt(actualIntStart) == '0') {
+ actualIntStart++;
+ }
+
+ // Find the ending position of the integer part
+ for (intEnd = actualIntStart;
+ intEnd < len && TypeValidator.isDigit(content.charAt(intEnd));
+ intEnd++);
+
+ // Not reached the end yet
+ if (intEnd < len) {
+ // the remaining part is not ".DDD", error
+ if (content.charAt(intEnd) != '.')
+ throw new NumberFormatException();
+
+ // fraction part starts after '.', and ends at the end of the input
+ fracStart = intEnd + 1;
+ fracEnd = len;
+ }
+
+ // no integer part, no fraction part, error.
+ if (intStart == intEnd && fracStart == fracEnd)
+ throw new NumberFormatException();
+
+ // ignore trailing zeroes in fraction part
+ while (fracEnd > fracStart && content.charAt(fracEnd-1) == '0') {
+ fracEnd--;
+ }
+
+ // check whether there is non-digit characters in the fraction part
+ for (int fracPos = fracStart; fracPos < fracEnd; fracPos++) {
+ if (!TypeValidator.isDigit(content.charAt(fracPos)))
+ throw new NumberFormatException();
+ }
+
+ intDigits = intEnd - actualIntStart;
+ fracDigits = fracEnd - fracStart;
+ totalDigits = intDigits + fracDigits;
+
+ if (intDigits > 0) {
+ ivalue = content.substring(actualIntStart, intEnd);
+ if (fracDigits > 0)
+ fvalue = content.substring(fracStart, fracEnd);
+ }
+ else {
+ if (fracDigits > 0) {
+ fvalue = content.substring(fracStart, fracEnd);
+ }
+ else {
+ // ".00", treat it as "0"
+ sign = 0;
+ }
+ }
+ }
+ void initI(String content) throws NumberFormatException {
+ int len = content.length();
+ if (len == 0)
+ throw new NumberFormatException();
+
+ // these 2 variables are used to indicate where the integre start/end.
+ int intStart = 0, intEnd = 0;
+
+ // Deal with leading sign symbol if present
+ if (content.charAt(0) == '+') {
+ // skip '+', so intStart should be 1
+ intStart = 1;
+ }
+ else if (content.charAt(0) == '-') {
+ // keep '-', so intStart is stil 0
+ intStart = 1;
+ sign = -1;
+ }
+
+ // skip leading zeroes in integer part
+ int actualIntStart = intStart;
+ while (actualIntStart < len && content.charAt(actualIntStart) == '0') {
+ actualIntStart++;
+ }
+
+ // Find the ending position of the integer part
+ for (intEnd = actualIntStart;
+ intEnd < len && TypeValidator.isDigit(content.charAt(intEnd));
+ intEnd++);
+
+ // Not reached the end yet, error
+ if (intEnd < len)
+ throw new NumberFormatException();
+
+ // no integer part, error.
+ if (intStart == intEnd)
+ throw new NumberFormatException();
+
+ intDigits = intEnd - actualIntStart;
+ fracDigits = 0;
+ totalDigits = intDigits;
+
+ if (intDigits > 0) {
+ ivalue = content.substring(actualIntStart, intEnd);
+ }
+ else {
+ // "00", treat it as "0"
+ sign = 0;
+ }
+
+ integer = true;
+ }
+ public boolean equals(Object val) {
+ if (val == this)
+ return true;
+
+ if (!(val instanceof XDecimal))
+ return false;
+ XDecimal oval = (XDecimal)val;
+
+ if (sign != oval.sign)
+ return false;
+ if (sign == 0)
+ return true;
+
+ return intDigits == oval.intDigits && fracDigits == oval.fracDigits &&
+ ivalue.equals(oval.ivalue) && fvalue.equals(oval.fvalue);
+ }
+ public int compareTo(XDecimal val) {
+ if (sign != val.sign)
+ return sign > val.sign ? 1 : -1;
+ if (sign == 0)
+ return 0;
+ return sign * intComp(val);
+ }
+ private int intComp(XDecimal val) {
+ if (intDigits != val.intDigits)
+ return intDigits > val.intDigits ? 1 : -1;
+ int ret = ivalue.compareTo(val.ivalue);
+ if (ret != 0)
+ return ret > 0 ? 1 : -1;;
+ ret = fvalue.compareTo(val.fvalue);
+ return ret == 0 ? 0 : (ret > 0 ? 1 : -1);
+ }
+ private String canonical;
+ public synchronized String toString() {
+ if (canonical == null) {
+ makeCanonical();
+ }
+ return canonical;
+ }
+
+ private void makeCanonical() {
+ if (sign == 0) {
+ if (integer)
+ canonical = "0";
+ else
+ canonical = "0.0";
+ return;
+ }
+ if (integer && sign > 0) {
+ canonical = ivalue;
+ return;
+ }
+ // for -0.1, total digits is 1, so we need 3 extra spots
+ StringBuffer buffer = new StringBuffer(totalDigits+3);
+ if (sign == -1)
+ buffer.append('-');
+ if (intDigits != 0)
+ buffer.append(ivalue);
+ else
+ buffer.append('0');
+ if (!integer) {
+ buffer.append('.');
+ if (fracDigits != 0) {
+ buffer.append(fvalue);
+ }
+ else {
+ buffer.append('0');
+ }
+ }
+ canonical = buffer.toString();
+ }
+
+ public BigDecimal getBigDecimal() {
+ if (sign == 0) {
+ return new BigDecimal(BigInteger.ZERO);
+ }
+ return new BigDecimal(toString());
+ }
+
+ public BigInteger getBigInteger() throws NumberFormatException {
+ if (fracDigits != 0) {
+ throw new NumberFormatException();
+ }
+ if (sign == 0) {
+ return BigInteger.ZERO;
+ }
+ if (sign == 1) {
+ return new BigInteger(ivalue);
+ }
+ return new BigInteger("-" + ivalue);
+ }
+
+ public long getLong() throws NumberFormatException {
+ if (fracDigits != 0) {
+ throw new NumberFormatException();
+ }
+ if (sign == 0) {
+ return 0L;
+ }
+ if (sign == 1) {
+ return Long.parseLong(ivalue);
+ }
+ return Long.parseLong("-" + ivalue);
+ }
+
+ public int getInt() throws NumberFormatException {
+ if (fracDigits != 0) {
+ throw new NumberFormatException();
+ }
+ if (sign == 0) {
+ return 0;
+ }
+ if (sign == 1) {
+ return Integer.parseInt(ivalue);
+ }
+ return Integer.parseInt("-" + ivalue);
+ }
+
+ public short getShort() throws NumberFormatException {
+ if (fracDigits != 0) {
+ throw new NumberFormatException();
+ }
+ if (sign == 0) {
+ return 0;
+ }
+ if (sign == 1) {
+ return Short.parseShort(ivalue);
+ }
+ return Short.parseShort("-" + ivalue);
+ }
+
+ public byte getByte() throws NumberFormatException {
+ if (fracDigits != 0) {
+ throw new NumberFormatException();
+ }
+ if (sign == 0) {
+ return 0;
+ }
+ if (sign == 1) {
+ return Byte.parseByte(ivalue);
+ }
+ return Byte.parseByte("-" + ivalue);
+ }
+ }
+} // class DecimalDV
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DoubleDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DoubleDV.java
new file mode 100644
index 0000000..61454bf
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DoubleDV.java
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.xs.datatypes.XSDouble;
+
+/**
+ * Represent the schema type "double"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class DoubleDV extends TypeValidator {
+
+ public short getAllowedFacets(){
+ return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE );
+ }//getAllowedFacets()
+
+ //convert a String to Double form, we have to take care of cases specified in spec like INF, -INF and NaN
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ try{
+ return new XDouble(content);
+ } catch (NumberFormatException ex){
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "double"});
+ }
+ }//getActualValue()
+
+ // Can't call Double#compareTo method, because it's introduced in jdk 1.2
+ public int compare(Object value1, Object value2) {
+ return ((XDouble)value1).compareTo((XDouble)value2);
+ }//compare()
+
+ //distinguishes between identity and equality for double datatype
+ //0.0 is equal but not identical to -0.0
+ public boolean isIdentical (Object value1, Object value2) {
+ if (value2 instanceof XDouble) {
+ return ((XDouble)value1).isIdentical((XDouble)value2);
+ }
+ return false;
+ }//isIdentical()
+
+ /**
+ * Returns true if it's possible that the given
+ * string represents a valid floating point value
+ * (excluding NaN, INF and -INF).
+ */
+ static boolean isPossibleFP(String val) {
+ final int length = val.length();
+ for (int i = 0; i < length; ++i) {
+ char c = val.charAt(i);
+ if (!(c >= '0' && c <= '9' || c == '.' ||
+ c == '-' || c == '+' || c == 'E' || c == 'e')) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static final class XDouble implements XSDouble {
+ private final double value;
+ public XDouble(String s) throws NumberFormatException {
+ if (isPossibleFP(s)) {
+ value = Double.parseDouble(s);
+ }
+ else if ( s.equals("INF") ) {
+ value = Double.POSITIVE_INFINITY;
+ }
+ else if ( s.equals("-INF") ) {
+ value = Double.NEGATIVE_INFINITY;
+ }
+ else if ( s.equals("NaN" ) ) {
+ value = Double.NaN;
+ }
+ else {
+ throw new NumberFormatException(s);
+ }
+ }
+
+ public boolean equals(Object val) {
+ if (val == this)
+ return true;
+
+ if (!(val instanceof XDouble))
+ return false;
+ XDouble oval = (XDouble)val;
+
+ // NOTE: we don't distinguish 0.0 from -0.0
+ if (value == oval.value)
+ return true;
+
+ if (value != value && oval.value != oval.value)
+ return true;
+
+ return false;
+ }
+
+ public int hashCode() {
+ // This check is necessary because doubleToLongBits(+0) != doubleToLongBits(-0)
+ if (value == 0d) {
+ return 0;
+ }
+ long v = Double.doubleToLongBits(value);
+ return (int) (v ^ (v >>> 32));
+ }
+
+ // NOTE: 0.0 is equal but not identical to -0.0
+ public boolean isIdentical (XDouble val) {
+ if (val == this) {
+ return true;
+ }
+
+ if (value == val.value) {
+ return (value != 0.0d ||
+ (Double.doubleToLongBits(value) == Double.doubleToLongBits(val.value)));
+ }
+
+ if (value != value && val.value != val.value)
+ return true;
+
+ return false;
+ }
+
+ private int compareTo(XDouble val) {
+ double oval = val.value;
+
+ // this < other
+ if (value < oval)
+ return -1;
+ // this > other
+ if (value > oval)
+ return 1;
+ // this == other
+ // NOTE: we don't distinguish 0.0 from -0.0
+ if (value == oval)
+ return 0;
+
+ // one of the 2 values or both is/are NaN(s)
+
+ if (value != value) {
+ // this = NaN = other
+ if (oval != oval)
+ return 0;
+ // this is NaN <> other
+ return INDETERMINATE;
+ }
+
+ // other is NaN <> this
+ return INDETERMINATE;
+ }
+
+ private String canonical;
+ public synchronized String toString() {
+ if (canonical == null) {
+ if (value == Double.POSITIVE_INFINITY)
+ canonical = "INF";
+ else if (value == Double.NEGATIVE_INFINITY)
+ canonical = "-INF";
+ else if (value != value)
+ canonical = "NaN";
+ // NOTE: we don't distinguish 0.0 from -0.0
+ else if (value == 0)
+ canonical = "0.0E1";
+ else {
+ // REVISIT: use the java algorithm for now, because we
+ // don't know what to output for 1.1d (which is no
+ // actually 1.1)
+ canonical = Double.toString(value);
+ // if it contains 'E', then it should be a valid schema
+ // canonical representation
+ if (canonical.indexOf('E') == -1) {
+ int len = canonical.length();
+ // at most 3 longer: E, -, 9
+ char[] chars = new char[len+3];
+ canonical.getChars(0, len, chars, 0);
+ // expected decimal point position
+ int edp = chars[0] == '-' ? 2 : 1;
+ // for non-zero integer part
+ if (value >= 1 || value <= -1) {
+ // decimal point position
+ int dp = canonical.indexOf('.');
+ // move the digits: ddd.d --> d.ddd
+ for (int i = dp; i > edp; i--) {
+ chars[i] = chars[i-1];
+ }
+ chars[edp] = '.';
+ // trim trailing zeros: d00.0 --> d.000 --> d.
+ while (chars[len-1] == '0')
+ len--;
+ // add the last zero if necessary: d. --> d.0
+ if (chars[len-1] == '.')
+ len++;
+ // append E: d.dd --> d.ddE
+ chars[len++] = 'E';
+ // how far we shifted the decimal point
+ int shift = dp - edp;
+ // append the exponent --> d.ddEd
+ // the exponent is at most 7
+ chars[len++] = (char)(shift + '0');
+ }
+ else {
+ // non-zero digit point
+ int nzp = edp + 1;
+ // skip zeros: 0.003
+ while (chars[nzp] == '0')
+ nzp++;
+ // put the first non-zero digit to the left of '.'
+ chars[edp-1] = chars[nzp];
+ chars[edp] = '.';
+ // move other digits (non-zero) to the right of '.'
+ for (int i = nzp+1, j = edp+1; i < len; i++, j++)
+ chars[j] = chars[i];
+ // adjust the length
+ len -= nzp - edp;
+ // append 0 if nessary: 0.03 --> 3. --> 3.0
+ if (len == edp + 1)
+ chars[len++] = '0';
+ // append E-: d.dd --> d.ddE-
+ chars[len++] = 'E';
+ chars[len++] = '-';
+ // how far we shifted the decimal point
+ int shift = nzp - edp;
+ // append the exponent --> d.ddEd
+ // the exponent is at most 3
+ chars[len++] = (char)(shift + '0');
+ }
+ canonical = new String(chars, 0, len);
+ }
+ }
+ }
+ return canonical;
+ }
+ public double getValue() {
+ return value;
+ }
+ }
+} // class DoubleDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DurationDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DurationDV.java
new file mode 100644
index 0000000..4ba3cd3
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/DurationDV.java
@@ -0,0 +1,387 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.Duration;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Validator for <duration> datatype (W3C Schema Datatypes)
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani
+ * @author Gopal Sharma, SUN Microsystem Inc.
+ * @version $Id$
+ */
+public class DurationDV extends AbstractDateTimeDV {
+
+ public static final int DURATION_TYPE = 0;
+ public static final int YEARMONTHDURATION_TYPE = 1;
+ public static final int DAYTIMEDURATION_TYPE = 2;
+ // order-relation on duration is a partial order. The dates below are used to
+ // for comparison of 2 durations, based on the fact that
+ // duration x and y is x<=y iff s+x<=s+y
+ // see 3.2.6 duration W3C schema datatype specs
+ //
+ // the dates are in format: {CCYY,MM,DD, H, S, M, MS, timezone}
+ private final static DateTimeData[] DATETIMES= {
+ new DateTimeData(1696, 9, 1, 0, 0, 0, 'Z', null, true, null),
+ new DateTimeData(1697, 2, 1, 0, 0, 0, 'Z', null, true, null),
+ new DateTimeData(1903, 3, 1, 0, 0, 0, 'Z', null, true, null),
+ new DateTimeData(1903, 7, 1, 0, 0, 0, 'Z', null, true, null)};
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException{
+ try{
+ return parse(content, DURATION_TYPE);
+ } catch (Exception ex) {
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "duration"});
+ }
+ }
+
+ /**
+ * Parses, validates and computes normalized version of duration object
+ *
+ * @param str The lexical representation of duration object PnYn MnDTnH nMnS
+ * @param durationType
+ * @return normalized date representation
+ * @exception SchemaDateTimeException Invalid lexical representation
+ */
+ protected DateTimeData parse(String str, int durationType) throws SchemaDateTimeException{
+ int len = str.length();
+ DateTimeData date= new DateTimeData(str, this);
+
+ int start = 0;
+ char c=str.charAt(start++);
+ if ( c!='P' && c!='-' ) {
+ throw new SchemaDateTimeException();
+ }
+ else {
+ date.utc=(c=='-')?'-':0;
+ if ( c=='-' && str.charAt(start++)!='P' ) {
+ throw new SchemaDateTimeException();
+ }
+ }
+
+ int negate = 1;
+ //negative duration
+ if ( date.utc=='-' ) {
+ negate = -1;
+
+ }
+ //at least one number and designator must be seen after P
+ boolean designator = false;
+
+ int endDate = indexOf (str, start, len, 'T');
+ if ( endDate == -1 ) {
+ endDate = len;
+ }
+ else if (durationType == YEARMONTHDURATION_TYPE) {
+ throw new SchemaDateTimeException();
+ }
+
+ //find 'Y'
+ int end = indexOf (str, start, endDate, 'Y');
+ if ( end!=-1 ) {
+
+ if (durationType == DAYTIMEDURATION_TYPE) {
+ throw new SchemaDateTimeException();
+ }
+
+ //scan year
+ date.year=negate * parseInt(str,start,end);
+ start = end+1;
+ designator = true;
+ }
+
+ end = indexOf (str, start, endDate, 'M');
+ if ( end!=-1 ) {
+
+ if (durationType == DAYTIMEDURATION_TYPE) {
+ throw new SchemaDateTimeException();
+ }
+
+ //scan month
+ date.month=negate * parseInt(str,start,end);
+ start = end+1;
+ designator = true;
+ }
+
+ end = indexOf (str, start, endDate, 'D');
+ if ( end!=-1 ) {
+
+ if(durationType == YEARMONTHDURATION_TYPE) {
+ throw new SchemaDateTimeException();
+ }
+
+ //scan day
+ date.day=negate * parseInt(str,start,end);
+ start = end+1;
+ designator = true;
+ }
+
+ if ( len == endDate && start!=len ) {
+ throw new SchemaDateTimeException();
+ }
+ if ( len !=endDate ) {
+
+ //scan hours, minutes, seconds
+ //REVISIT: can any item include a decimal fraction or only seconds?
+ //
+
+ end = indexOf (str, ++start, len, 'H');
+ if ( end!=-1 ) {
+ //scan hours
+ date.hour=negate * parseInt(str,start,end);
+ start=end+1;
+ designator = true;
+ }
+
+ end = indexOf (str, start, len, 'M');
+ if ( end!=-1 ) {
+ //scan min
+ date.minute=negate * parseInt(str,start,end);
+ start=end+1;
+ designator = true;
+ }
+
+ end = indexOf (str, start, len, 'S');
+ if ( end!=-1 ) {
+ //scan seconds
+ date.second = negate * parseSecond(str, start, end);
+ start=end+1;
+ designator = true;
+ }
+ // no additional data shouls appear after last item
+ // P1Y1M1DT is illigal value as well
+ if ( start != len || str.charAt(--start)=='T' ) {
+ throw new SchemaDateTimeException();
+ }
+ }
+
+ if ( !designator ) {
+ throw new SchemaDateTimeException();
+ }
+
+ return date;
+ }
+
+ /**
+ * Compares 2 given durations. (refer to W3C Schema Datatypes "3.2.6 duration")
+ *
+ * @param date1 Unnormalized duration
+ * @param date2 Unnormalized duration
+ * @param strict (min/max)Exclusive strict == true ( LESS_THAN ) or ( GREATER_THAN )
+ * (min/max)Inclusive strict == false (LESS_EQUAL) or (GREATER_EQUAL)
+ * @return INDETERMINATE if the order relationship between date1 and date2 is indeterminate.
+ * EQUAL if the order relation between date1 and date2 is EQUAL.
+ * If the strict parameter is true, return LESS_THAN if date1 is less than date2 and
+ * return GREATER_THAN if date1 is greater than date2.
+ * If the strict parameter is false, return LESS_THAN if date1 is less than OR equal to date2 and
+ * return GREATER_THAN if date1 is greater than OR equal to date2
+ */
+ protected short compareDates(DateTimeData date1, DateTimeData date2, boolean strict) {
+
+ //REVISIT: this is unoptimazed vs of comparing 2 durations
+ // Algorithm is described in 3.2.6.2 W3C Schema Datatype specs
+ //
+
+ //add constA to both durations
+ short resultA, resultB= INDETERMINATE;
+ //try and see if the objects are equal
+ resultA = compareOrder (date1, date2);
+ if ( resultA == 0 ) {
+ return 0;
+ }
+
+ DateTimeData[] result = new DateTimeData[2];
+ result[0] = new DateTimeData(null, this);
+ result[1] = new DateTimeData(null, this);
+
+ //long comparison algorithm is required
+ DateTimeData tempA = addDuration (date1, DATETIMES[0], result[0]);
+ DateTimeData tempB = addDuration (date2, DATETIMES[0], result[1]);
+ resultA = compareOrder(tempA, tempB);
+ if ( resultA == INDETERMINATE ) {
+ return INDETERMINATE;
+ }
+
+ tempA = addDuration(date1, DATETIMES[1], result[0]);
+ tempB = addDuration(date2, DATETIMES[1], result[1]);
+ resultB = compareOrder(tempA, tempB);
+ resultA = compareResults(resultA, resultB, strict);
+ if (resultA == INDETERMINATE) {
+ return INDETERMINATE;
+ }
+
+ tempA = addDuration(date1, DATETIMES[2], result[0]);
+ tempB = addDuration(date2, DATETIMES[2], result[1]);
+ resultB = compareOrder(tempA, tempB);
+ resultA = compareResults(resultA, resultB, strict);
+ if (resultA == INDETERMINATE) {
+ return INDETERMINATE;
+ }
+
+ tempA = addDuration(date1, DATETIMES[3], result[0]);
+ tempB = addDuration(date2, DATETIMES[3], result[1]);
+ resultB = compareOrder(tempA, tempB);
+ resultA = compareResults(resultA, resultB, strict);
+
+ return resultA;
+ }
+
+ private short compareResults(short resultA, short resultB, boolean strict){
+
+ if ( resultB == INDETERMINATE ) {
+ return INDETERMINATE;
+ }
+ else if ( resultA!=resultB && strict ) {
+ return INDETERMINATE;
+ }
+ else if ( resultA!=resultB && !strict ) {
+ if ( resultA!=0 && resultB!=0 ) {
+ return INDETERMINATE;
+ }
+ else {
+ return (resultA!=0)?resultA:resultB;
+ }
+ }
+ return resultA;
+ }
+
+ private DateTimeData addDuration(DateTimeData date, DateTimeData addto, DateTimeData duration) {
+
+ //REVISIT: some code could be shared between normalize() and this method,
+ // however is it worth moving it? The structures are different...
+ //
+
+ resetDateObj(duration);
+ //add months (may be modified additionaly below)
+ int temp = addto.month + date.month;
+ duration.month = modulo (temp, 1, 13);
+ int carry = fQuotient (temp, 1, 13);
+
+ //add years (may be modified additionaly below)
+ duration.year=addto.year + date.year + carry;
+
+ //add seconds
+ double dtemp = addto.second + date.second;
+ carry = (int)Math.floor(dtemp/60);
+ duration.second = dtemp - carry*60;
+
+ //add minutes
+ temp = addto.minute +date.minute + carry;
+ carry = fQuotient (temp, 60);
+ duration.minute= mod(temp, 60, carry);
+
+ //add hours
+ temp = addto.hour + date.hour + carry;
+ carry = fQuotient(temp, 24);
+ duration.hour = mod(temp, 24, carry);
+
+
+ duration.day=addto.day + date.day + carry;
+
+ while ( true ) {
+
+ temp=maxDayInMonthFor(duration.year, duration.month);
+ if ( duration.day < 1 ) { //original duration was negative
+ duration.day = duration.day + maxDayInMonthFor(duration.year, duration.month-1);
+ carry=-1;
+ }
+ else if ( duration.day > temp ) {
+ duration.day = duration.day - temp;
+ carry=1;
+ }
+ else {
+ break;
+ }
+ temp = duration.month+carry;
+ duration.month = modulo(temp, 1, 13);
+ duration.year = duration.year+fQuotient(temp, 1, 13);
+ }
+
+ duration.utc='Z';
+ return duration;
+ }
+
+ protected double parseSecond(String buffer, int start, int end)
+ throws NumberFormatException {
+ int dot = -1;
+ for (int i = start; i < end; i++) {
+ char ch = buffer.charAt(i);
+ if (ch == '.')
+ dot = i;
+ else if (ch > '9' || ch < '0')
+ throw new NumberFormatException("'" + buffer + "' has wrong format");
+ }
+ if (dot+1 == end) {
+ throw new NumberFormatException("'" + buffer + "' has wrong format");
+ }
+ double value = Double.parseDouble(buffer.substring(start, end));
+ if (value == Double.POSITIVE_INFINITY) {
+ throw new NumberFormatException("'" + buffer + "' has wrong format");
+ }
+ return value;
+ }
+
+ protected String dateToString(DateTimeData date) {
+ StringBuffer message = new StringBuffer(30);
+ if ( date.year<0 || date.month<0 || date.day<0
+ || date.hour<0 || date.minute<0 || date.second<0) {
+ message.append('-');
+ }
+ message.append('P');
+ message.append((date.year < 0?-1:1) * date.year);
+ message.append('Y');
+ message.append((date.month < 0?-1:1) * date.month);
+ message.append('M');
+ message.append((date.day < 0?-1:1) * date.day);
+ message.append('D');
+ message.append('T');
+ message.append((date.hour < 0?-1:1) * date.hour);
+ message.append('H');
+ message.append((date.minute < 0?-1:1) * date.minute);
+ message.append('M');
+ append2(message, (date.second < 0?-1:1) * date.second);
+ message.append('S');
+
+ return message.toString();
+ }
+
+ protected Duration getDuration(DateTimeData date) {
+ int sign = 1;
+ if ( date.year<0 || date.month<0 || date.day<0
+ || date.hour<0 || date.minute<0 || date.second<0) {
+ sign = -1;
+ }
+ return datatypeFactory.newDuration(sign == 1,
+ date.year != DatatypeConstants.FIELD_UNDEFINED?BigInteger.valueOf(sign*date.year):null,
+ date.month != DatatypeConstants.FIELD_UNDEFINED?BigInteger.valueOf(sign*date.month):null,
+ date.day != DatatypeConstants.FIELD_UNDEFINED?BigInteger.valueOf(sign*date.day):null,
+ date.hour != DatatypeConstants.FIELD_UNDEFINED?BigInteger.valueOf(sign*date.hour):null,
+ date.minute != DatatypeConstants.FIELD_UNDEFINED?BigInteger.valueOf(sign*date.minute):null,
+ date.second != DatatypeConstants.FIELD_UNDEFINED?new BigDecimal(String.valueOf(sign*date.second)):null);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/EntityDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/EntityDV.java
new file mode 100644
index 0000000..8b268eb
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/EntityDV.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.XMLChar;
+
+/**
+ * Represent the schema type "entity"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class EntityDV extends TypeValidator {
+
+ public short getAllowedFacets(){
+ return (XSSimpleTypeDecl.FACET_LENGTH | XSSimpleTypeDecl.FACET_MINLENGTH | XSSimpleTypeDecl.FACET_MAXLENGTH | XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_ENUMERATION | XSSimpleTypeDecl.FACET_WHITESPACE );
+ }
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ if (!XMLChar.isValidNCName(content)) {
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "NCName"});
+ }
+
+ return content;
+ }
+
+ public void checkExtraRules(Object value, ValidationContext context) throws InvalidDatatypeValueException {
+ if (!context.isEntityUnparsed((String)value)) {
+ throw new InvalidDatatypeValueException("UndeclaredEntity", new Object[]{value});
+ }
+ }
+
+} // class EntityDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/ExtendedSchemaDVFactoryImpl.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/ExtendedSchemaDVFactoryImpl.java
new file mode 100644
index 0000000..110bd15
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/ExtendedSchemaDVFactoryImpl.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.XSSimpleType;
+import org.apache.xerces.util.SymbolHash;
+
+/**
+ * A special factory to create/return built-in schema DVs and create user-defined DVs
+ * that includes anyAtomicType, yearMonthDuration and dayTimeDuration
+ *
+ * @xerces.internal
+ *
+ * @author Khaled Noaman, IBM
+ *
+ * @version $Id$
+ */
+public class ExtendedSchemaDVFactoryImpl extends BaseSchemaDVFactory {
+
+ static SymbolHash fBuiltInTypes = new SymbolHash();
+ static {
+ createBuiltInTypes();
+ }
+
+ // create all built-in types
+ static void createBuiltInTypes() {
+ final String ANYATOMICTYPE = "anyAtomicType";
+ final String DURATION = "duration";
+ final String YEARMONTHDURATION = "yearMonthDuration";
+ final String DAYTIMEDURATION = "dayTimeDuration";
+
+ createBuiltInTypes(fBuiltInTypes, XSSimpleTypeDecl.fAnyAtomicType);
+
+ // add anyAtomicType
+ fBuiltInTypes.put(ANYATOMICTYPE, XSSimpleTypeDecl.fAnyAtomicType);
+
+ // add 2 duration types
+ XSSimpleTypeDecl durationDV = (XSSimpleTypeDecl)fBuiltInTypes.get(DURATION);
+ fBuiltInTypes.put(YEARMONTHDURATION, new XSSimpleTypeDecl(durationDV, YEARMONTHDURATION, XSSimpleTypeDecl.DV_YEARMONTHDURATION, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSSimpleTypeDecl.YEARMONTHDURATION_DT));
+ fBuiltInTypes.put(DAYTIMEDURATION, new XSSimpleTypeDecl(durationDV, DAYTIMEDURATION, XSSimpleTypeDecl.DV_DAYTIMEDURATION, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSSimpleTypeDecl.DAYTIMEDURATION_DT));
+ } //createBuiltInTypes()
+
+ /**
+ * Get a built-in simple type of the given name
+ * REVISIT: its still not decided within the Schema WG how to define the
+ * ur-types and if all simple types should be derived from a
+ * complex type, so as of now we ignore the fact that anySimpleType
+ * is derived from anyType, and pass 'null' as the base of
+ * anySimpleType. It needs to be changed as per the decision taken.
+ *
+ * @param name the name of the datatype
+ * @return the datatype validator of the given name
+ */
+ public XSSimpleType getBuiltInType(String name) {
+ return (XSSimpleType)fBuiltInTypes.get(name);
+ }
+
+ /**
+ * get all built-in simple types, which are stored in a hashtable keyed by
+ * the name
+ *
+ * @return a hashtable which contains all built-in simple types
+ */
+ public SymbolHash getBuiltInTypes() {
+ return (SymbolHash)fBuiltInTypes.makeClone();
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/FloatDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/FloatDV.java
new file mode 100644
index 0000000..ce5f984
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/FloatDV.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.xs.datatypes.XSFloat;
+
+/**
+ * Represent the schema type "float"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class FloatDV extends TypeValidator {
+
+ public short getAllowedFacets(){
+ return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE );
+ }//getAllowedFacets()
+
+ //convert a String to Float form, we have to take care of cases specified in spec like INF, -INF and NaN
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ try{
+ return new XFloat(content);
+ } catch (NumberFormatException ex){
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "float"});
+ }
+ }//getActualValue()
+
+ // Can't call Float#compareTo method, because it's introduced in jdk 1.2
+ public int compare(Object value1, Object value2){
+ return ((XFloat)value1).compareTo((XFloat)value2);
+ }//compare()
+
+ //distinguishes between identity and equality for float datatype
+ //0.0 is equal but not identical to -0.0
+ public boolean isIdentical (Object value1, Object value2) {
+ if (value2 instanceof XFloat) {
+ return ((XFloat)value1).isIdentical((XFloat)value2);
+ }
+ return false;
+ }//isIdentical()
+
+ private static final class XFloat implements XSFloat {
+
+ private final float value;
+ public XFloat(String s) throws NumberFormatException {
+ if (DoubleDV.isPossibleFP(s)) {
+ value = Float.parseFloat(s);
+ }
+ else if ( s.equals("INF") ) {
+ value = Float.POSITIVE_INFINITY;
+ }
+ else if ( s.equals("-INF") ) {
+ value = Float.NEGATIVE_INFINITY;
+ }
+ else if ( s.equals("NaN") ) {
+ value = Float.NaN;
+ }
+ else {
+ throw new NumberFormatException(s);
+ }
+ }
+
+ public boolean equals(Object val) {
+ if (val == this)
+ return true;
+
+ if (!(val instanceof XFloat))
+ return false;
+ XFloat oval = (XFloat)val;
+
+ // NOTE: we don't distinguish 0.0 from -0.0
+ if (value == oval.value)
+ return true;
+
+ if (value != value && oval.value != oval.value)
+ return true;
+
+ return false;
+ }
+
+ public int hashCode() {
+ // This check is necessary because floatToIntBits(+0) != floatToIntBits(-0)
+ return (value == 0f) ? 0 : Float.floatToIntBits(value);
+ }
+
+ // NOTE: 0.0 is equal but not identical to -0.0
+ public boolean isIdentical (XFloat val) {
+ if (val == this) {
+ return true;
+ }
+
+ if (value == val.value) {
+ return (value != 0.0f ||
+ (Float.floatToIntBits(value) == Float.floatToIntBits(val.value)));
+ }
+
+ if (value != value && val.value != val.value)
+ return true;
+
+ return false;
+ }
+
+ private int compareTo(XFloat val) {
+ float oval = val.value;
+
+ // this < other
+ if (value < oval)
+ return -1;
+ // this > other
+ if (value > oval)
+ return 1;
+ // this == other
+ // NOTE: we don't distinguish 0.0 from -0.0
+ if (value == oval)
+ return 0;
+
+ // one of the 2 values or both is/are NaN(s)
+
+ if (value != value) {
+ // this = NaN = other
+ if (oval != oval)
+ return 0;
+ // this is NaN <> other
+ return INDETERMINATE;
+ }
+
+ // other is NaN <> this
+ return INDETERMINATE;
+ }
+
+ private String canonical;
+ public synchronized String toString() {
+ if (canonical == null) {
+ if (value == Float.POSITIVE_INFINITY)
+ canonical = "INF";
+ else if (value == Float.NEGATIVE_INFINITY)
+ canonical = "-INF";
+ else if (value != value)
+ canonical = "NaN";
+ // NOTE: we don't distinguish 0.0 from -0.0
+ else if (value == 0)
+ canonical = "0.0E1";
+ else {
+ // REVISIT: use the java algorithm for now, because we
+ // don't know what to output for 1.1f (which is no
+ // actually 1.1)
+ canonical = Float.toString(value);
+ // if it contains 'E', then it should be a valid schema
+ // canonical representation
+ if (canonical.indexOf('E') == -1) {
+ int len = canonical.length();
+ // at most 3 longer: E, -, 9
+ char[] chars = new char[len+3];
+ canonical.getChars(0, len, chars, 0);
+ // expected decimal point position
+ int edp = chars[0] == '-' ? 2 : 1;
+ // for non-zero integer part
+ if (value >= 1 || value <= -1) {
+ // decimal point position
+ int dp = canonical.indexOf('.');
+ // move the digits: ddd.d --> d.ddd
+ for (int i = dp; i > edp; i--) {
+ chars[i] = chars[i-1];
+ }
+ chars[edp] = '.';
+ // trim trailing zeros: d00.0 --> d.000 --> d.
+ while (chars[len-1] == '0')
+ len--;
+ // add the last zero if necessary: d. --> d.0
+ if (chars[len-1] == '.')
+ len++;
+ // append E: d.dd --> d.ddE
+ chars[len++] = 'E';
+ // how far we shifted the decimal point
+ int shift = dp - edp;
+ // append the exponent --> d.ddEd
+ // the exponent is at most 7
+ chars[len++] = (char)(shift + '0');
+ }
+ else {
+ // non-zero digit point
+ int nzp = edp + 1;
+ // skip zeros: 0.003
+ while (chars[nzp] == '0')
+ nzp++;
+ // put the first non-zero digit to the left of '.'
+ chars[edp-1] = chars[nzp];
+ chars[edp] = '.';
+ // move other digits (non-zero) to the right of '.'
+ for (int i = nzp+1, j = edp+1; i < len; i++, j++)
+ chars[j] = chars[i];
+ // adjust the length
+ len -= nzp - edp;
+ // append 0 if nessary: 0.03 --> 3. --> 3.0
+ if (len == edp + 1)
+ chars[len++] = '0';
+ // append E-: d.dd --> d.ddE-
+ chars[len++] = 'E';
+ chars[len++] = '-';
+ // how far we shifted the decimal point
+ int shift = nzp - edp;
+ // append the exponent --> d.ddEd
+ // the exponent is at most 3
+ chars[len++] = (char)(shift + '0');
+ }
+ canonical = new String(chars, 0, len);
+ }
+ }
+ }
+ return canonical;
+ }
+
+ public float getValue() {
+ return value;
+ }
+ }
+} // class FloatDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/FullDVFactory.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/FullDVFactory.java
new file mode 100644
index 0000000..5731aeb
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/FullDVFactory.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.XSFacets;
+import org.apache.xerces.impl.dv.XSSimpleType;
+import org.apache.xerces.util.SymbolHash;
+import org.apache.xerces.xs.XSConstants;
+
+/**
+ * the factory to create/return built-in schema DVs and create user-defined DVs
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class FullDVFactory extends BaseDVFactory {
+
+ static final String URI_SCHEMAFORSCHEMA = "http://www.w3.org/2001/XMLSchema";
+
+ // there are 45 types. 89 is the closest prime number to 45*2=90.
+ static SymbolHash fFullTypes = new SymbolHash(89);
+ static {
+ createBuiltInTypes(fFullTypes);
+ }
+
+ /**
+ * Get a built-in simple type of the given name
+ * REVISIT: its still not decided within the Schema WG how to define the
+ * ur-types and if all simple types should be derived from a
+ * complex type, so as of now we ignore the fact that anySimpleType
+ * is derived from anyType, and pass 'null' as the base of
+ * anySimpleType. It needs to be changed as per the decision taken.
+ *
+ * @param name the name of the datatype
+ * @return the datatype validator of the given name
+ */
+ public XSSimpleType getBuiltInType(String name) {
+ return (XSSimpleType)fFullTypes.get(name);
+ }
+
+ /**
+ * get all built-in simple types, which are stored in a hashtable keyed by
+ * the name
+ *
+ * @return a hashtable which contains all built-in simple types
+ */
+ public SymbolHash getBuiltInTypes() {
+ return (SymbolHash)fFullTypes.makeClone();
+ }
+
+ // create all built-in types
+ static void createBuiltInTypes(SymbolHash types) {
+ // create base types first
+ BaseDVFactory.createBuiltInTypes(types);
+
+ // full schema simple type names
+ final String DOUBLE = "double";
+ final String DURATION = "duration";
+ final String ENTITY = "ENTITY";
+ final String ENTITIES = "ENTITIES";
+ final String FLOAT = "float";
+ final String HEXBINARY = "hexBinary";
+ final String ID = "ID";
+ final String IDREF = "IDREF";
+ final String IDREFS = "IDREFS";
+ final String NAME = "Name";
+ final String NCNAME = "NCName";
+ final String NMTOKEN = "NMTOKEN";
+ final String NMTOKENS = "NMTOKENS";
+ final String LANGUAGE = "language";
+ final String NORMALIZEDSTRING = "normalizedString";
+ final String NOTATION = "NOTATION";
+ final String QNAME = "QName";
+ final String STRING = "string";
+ final String TOKEN = "token";
+
+ final XSFacets facets = new XSFacets();
+
+ XSSimpleTypeDecl anySimpleType = XSSimpleTypeDecl.fAnySimpleType;
+ XSSimpleTypeDecl stringDV = (XSSimpleTypeDecl)types.get(STRING);
+
+ types.put(FLOAT, new XSSimpleTypeDecl(anySimpleType, FLOAT, XSSimpleTypeDecl.DV_FLOAT, XSSimpleType.ORDERED_PARTIAL, true, true, true, true, XSConstants.FLOAT_DT));
+ types.put(DOUBLE, new XSSimpleTypeDecl(anySimpleType, DOUBLE, XSSimpleTypeDecl.DV_DOUBLE, XSSimpleType.ORDERED_PARTIAL, true, true, true, true, XSConstants.DOUBLE_DT));
+ types.put(DURATION, new XSSimpleTypeDecl(anySimpleType, DURATION, XSSimpleTypeDecl.DV_DURATION, XSSimpleType.ORDERED_PARTIAL, false, false, false, true, XSConstants.DURATION_DT));
+ types.put(HEXBINARY, new XSSimpleTypeDecl(anySimpleType, HEXBINARY, XSSimpleTypeDecl.DV_HEXBINARY, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.HEXBINARY_DT));
+ types.put(QNAME, new XSSimpleTypeDecl(anySimpleType, QNAME, XSSimpleTypeDecl.DV_QNAME, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.QNAME_DT));
+ types.put(NOTATION, new XSSimpleTypeDecl(anySimpleType, NOTATION, XSSimpleTypeDecl.DV_NOTATION, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.NOTATION_DT));
+
+ facets.whiteSpace = XSSimpleType.WS_REPLACE;
+ XSSimpleTypeDecl normalizedDV = new XSSimpleTypeDecl(stringDV, NORMALIZEDSTRING , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NORMALIZEDSTRING_DT);
+ normalizedDV.applyFacets1(facets, XSSimpleType.FACET_WHITESPACE, (short)0 );
+ types.put(NORMALIZEDSTRING, normalizedDV);
+
+ facets.whiteSpace = XSSimpleType.WS_COLLAPSE;
+ XSSimpleTypeDecl tokenDV = new XSSimpleTypeDecl(normalizedDV, TOKEN , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.TOKEN_DT);
+ tokenDV.applyFacets1(facets, XSSimpleType.FACET_WHITESPACE, (short)0 );
+ types.put(TOKEN, tokenDV);
+
+ facets.whiteSpace = XSSimpleType.WS_COLLAPSE;
+ facets.pattern = "([a-zA-Z]{1,8})(-[a-zA-Z0-9]{1,8})*";
+ XSSimpleTypeDecl languageDV = new XSSimpleTypeDecl(tokenDV, LANGUAGE , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.LANGUAGE_DT);
+ languageDV.applyFacets1(facets, (short)(XSSimpleType.FACET_WHITESPACE | XSSimpleType.FACET_PATTERN) ,(short)0);
+ types.put(LANGUAGE, languageDV);
+
+ facets.whiteSpace = XSSimpleType.WS_COLLAPSE;
+ XSSimpleTypeDecl nameDV = new XSSimpleTypeDecl(tokenDV, NAME , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NAME_DT);
+ nameDV.applyFacets1(facets, XSSimpleType.FACET_WHITESPACE, (short)0, XSSimpleTypeDecl.SPECIAL_PATTERN_NAME);
+ types.put(NAME, nameDV);
+
+ facets.whiteSpace = XSSimpleType.WS_COLLAPSE;
+ XSSimpleTypeDecl ncnameDV = new XSSimpleTypeDecl(nameDV, NCNAME , URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NCNAME_DT) ;
+ ncnameDV.applyFacets1(facets, XSSimpleType.FACET_WHITESPACE, (short)0, XSSimpleTypeDecl.SPECIAL_PATTERN_NCNAME);
+ types.put(NCNAME, ncnameDV);
+
+ types.put(ID, new XSSimpleTypeDecl(ncnameDV, ID, XSSimpleTypeDecl.DV_ID, XSSimpleType.ORDERED_FALSE, false, false, false , true, XSConstants.ID_DT));
+ XSSimpleTypeDecl idrefDV = new XSSimpleTypeDecl(ncnameDV, IDREF , XSSimpleTypeDecl.DV_IDREF, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.IDREF_DT);
+ types.put(IDREF, idrefDV);
+
+ facets.minLength = 1;
+ XSSimpleTypeDecl tempDV = new XSSimpleTypeDecl(null, URI_SCHEMAFORSCHEMA, (short)0, idrefDV, true, null);
+ XSSimpleTypeDecl idrefsDV = new XSSimpleTypeDecl(tempDV, IDREFS, URI_SCHEMAFORSCHEMA, (short)0, false, null);
+ idrefsDV.applyFacets1(facets, XSSimpleType.FACET_MINLENGTH, (short)0);
+ types.put(IDREFS, idrefsDV);
+
+ XSSimpleTypeDecl entityDV = new XSSimpleTypeDecl(ncnameDV, ENTITY , XSSimpleTypeDecl.DV_ENTITY, XSSimpleType.ORDERED_FALSE, false, false, false, true, XSConstants.ENTITY_DT);
+ types.put(ENTITY, entityDV);
+
+ facets.minLength = 1;
+ tempDV = new XSSimpleTypeDecl(null, URI_SCHEMAFORSCHEMA, (short)0, entityDV, true, null);
+ XSSimpleTypeDecl entitiesDV = new XSSimpleTypeDecl(tempDV, ENTITIES, URI_SCHEMAFORSCHEMA, (short)0, false, null);
+ entitiesDV.applyFacets1(facets, XSSimpleType.FACET_MINLENGTH, (short)0);
+ types.put(ENTITIES, entitiesDV);
+
+
+ facets.whiteSpace = XSSimpleType.WS_COLLAPSE;
+ XSSimpleTypeDecl nmtokenDV = new XSSimpleTypeDecl(tokenDV, NMTOKEN, URI_SCHEMAFORSCHEMA, (short)0, false, null, XSConstants.NMTOKEN_DT);
+ nmtokenDV.applyFacets1(facets, XSSimpleType.FACET_WHITESPACE, (short)0, XSSimpleTypeDecl.SPECIAL_PATTERN_NMTOKEN);
+ types.put(NMTOKEN, nmtokenDV);
+
+ facets.minLength = 1;
+ tempDV = new XSSimpleTypeDecl(null, URI_SCHEMAFORSCHEMA, (short)0, nmtokenDV, true, null);
+ XSSimpleTypeDecl nmtokensDV = new XSSimpleTypeDecl(tempDV, NMTOKENS, URI_SCHEMAFORSCHEMA, (short)0, false, null);
+ nmtokensDV.applyFacets1(facets, XSSimpleType.FACET_MINLENGTH, (short)0);
+ types.put(NMTOKENS, nmtokensDV);
+ }//createBuiltInTypes(SymbolHash)
+
+}//XFormsDVFactory
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/HexBinaryDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/HexBinaryDV.java
new file mode 100644
index 0000000..44591cb
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/HexBinaryDV.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.impl.dv.util.ByteListImpl;
+import org.apache.xerces.impl.dv.util.HexBin;
+
+/**
+ * Represent the schema type "hexBinary"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class HexBinaryDV extends TypeValidator {
+
+ public short getAllowedFacets(){
+ return (XSSimpleTypeDecl.FACET_LENGTH | XSSimpleTypeDecl.FACET_MINLENGTH | XSSimpleTypeDecl.FACET_MAXLENGTH | XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_ENUMERATION | XSSimpleTypeDecl.FACET_WHITESPACE );
+ }
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ byte[] decoded = HexBin.decode(content);
+ if (decoded == null)
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "hexBinary"});
+
+ return new XHex(decoded);
+ }
+
+ // length of a binary type is the number of bytes
+ public int getDataLength(Object value) {
+ return ((XHex)value).getLength();
+ }
+
+ private static final class XHex extends ByteListImpl {
+
+ public XHex(byte[] data) {
+ super(data);
+ }
+ public synchronized String toString() {
+ if (canonical == null) {
+ canonical = HexBin.encode(data);
+ }
+ return canonical;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof XHex))
+ return false;
+ byte[] odata = ((XHex)obj).data;
+ int len = data.length;
+ if (len != odata.length)
+ return false;
+ for (int i = 0; i < len; i++) {
+ if (data[i] != odata[i])
+ return false;
+ }
+ return true;
+ }
+
+ public int hashCode() {
+ int hash = 0;
+ for (int i = 0; i < data.length; ++i) {
+ hash = hash * 37 + (((int) data[i]) & 0xff);
+ }
+ return hash;
+ }
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/IDDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/IDDV.java
new file mode 100644
index 0000000..bee86c8
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/IDDV.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.XMLChar;
+
+/**
+ * Represent the schema type "ID"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class IDDV extends TypeValidator{
+
+ public short getAllowedFacets(){
+ return (XSSimpleTypeDecl.FACET_LENGTH | XSSimpleTypeDecl.FACET_MINLENGTH | XSSimpleTypeDecl.FACET_MAXLENGTH | XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_ENUMERATION | XSSimpleTypeDecl.FACET_WHITESPACE );
+ }
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ if (!XMLChar.isValidNCName(content)) {
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "NCName"});
+ }
+ return content;
+ }
+
+ public void checkExtraRules(Object value, ValidationContext context) throws InvalidDatatypeValueException {
+ String content = (String)value;
+ if (context.isIdDeclared(content))
+ throw new InvalidDatatypeValueException("cvc-id.2", new Object[]{content});
+ context.addId(content);
+ }
+} // class IDDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/IDREFDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/IDREFDV.java
new file mode 100644
index 0000000..c48696e
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/IDREFDV.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.XMLChar;
+
+/**
+ * Represent the schema type "IDREF"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class IDREFDV extends TypeValidator{
+
+ public short getAllowedFacets(){
+ return (XSSimpleTypeDecl.FACET_LENGTH | XSSimpleTypeDecl.FACET_MINLENGTH | XSSimpleTypeDecl.FACET_MAXLENGTH | XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_ENUMERATION | XSSimpleTypeDecl.FACET_WHITESPACE );
+ }
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ if (!XMLChar.isValidNCName(content)) {
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "NCName"});
+ }
+ return content;
+ }
+
+ public void checkExtraRules(Object value, ValidationContext context) throws InvalidDatatypeValueException {
+ context.addIdRef((String)value);
+ }
+
+}//IDREF class
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/IntegerDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/IntegerDV.java
new file mode 100644
index 0000000..3e24cb6
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/IntegerDV.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Represent the schema type "integer"
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class IntegerDV extends DecimalDV {
+
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
+ try {
+ return new XDecimal(content, true);
+ } catch (NumberFormatException nfe) {
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "integer"});
+ }
+ }
+
+} // class EntityDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/ListDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/ListDV.java
new file mode 100644
index 0000000..88c6b4b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/ListDV.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import java.util.AbstractList;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.xs.datatypes.ObjectList;
+
+/**
+ * Represent the schema list types
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class ListDV extends TypeValidator{
+
+ public short getAllowedFacets(){
+ return (XSSimpleTypeDecl.FACET_LENGTH | XSSimpleTypeDecl.FACET_MINLENGTH | XSSimpleTypeDecl.FACET_MAXLENGTH | XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_ENUMERATION | XSSimpleTypeDecl.FACET_WHITESPACE );
+ }
+
+ // this method should never be called: XSSimpleTypeDecl is responsible for
+ // calling the item type for the convertion
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException{
+ return content;
+ }
+
+ // length of a list type is the number of items in the list
+ public int getDataLength(Object value) {
+ return ((ListData)value).getLength();
+ }
+
+ final static class ListData extends AbstractList implements ObjectList {
+ final Object[] data;
+ private String canonical;
+ public ListData(Object[] data) {
+ this.data = data;
+ }
+ public synchronized String toString() {
+ if (canonical == null) {
+ int len = data.length;
+ StringBuffer buf = new StringBuffer();
+ if (len > 0) {
+ buf.append(data[0].toString());
+ }
+ for (int i = 1; i < len; i++) {
+ buf.append(' ');
+ buf.append(data[i].toString());
+ }
+ canonical = buf.toString();
+ }
+ return canonical;
+ }
+ public int getLength() {
+ return data.length;
+ }
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ListData))
+ return false;
+ Object[] odata = ((ListData)obj).data;
+
+ int count = data.length;
+ if (count != odata.length)
+ return false;
+
+ for (int i = 0 ; i < count ; i++) {
+ if (!data[i].equals(odata[i]))
+ return false;
+ }//end of loop
+
+ //everything went fine.
+ return true;
+ }
+
+ public int hashCode() {
+ int hash = 0;
+ for (int i = 0; i < data.length; ++i) {
+ hash ^= data[i].hashCode();
+ }
+ return hash;
+ }
+
+ public boolean contains(Object item) {
+ for (int i = 0;i < data.length; i++) {
+ if (item == data[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Object item(int index) {
+ if (index < 0 || index >= data.length) {
+ return null;
+ }
+ return data[index];
+ }
+
+ /*
+ * List methods
+ */
+
+ public Object get(int index) {
+ if (index >= 0 && index < data.length) {
+ return data[index];
+ }
+ throw new IndexOutOfBoundsException("Index: " + index);
+ }
+
+ public int size() {
+ return getLength();
+ }
+ }
+} // class ListDV
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/MonthDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/MonthDV.java
new file mode 100644
index 0000000..3e4259c
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/MonthDV.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Validator for <gMonth> datatype (W3C Schema Datatypes)
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani
+ * @author Gopal Sharma, SUN Microsystem Inc.
+ *
+ * @version $Id$
+ */
+
+public class MonthDV extends AbstractDateTimeDV {
+
+ /**
+ * Convert a string to a compiled form
+ *
+ * @param content The lexical representation of gMonth
+ * @return a valid and normalized gMonth object
+ */
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException{
+ try{
+ return parse(content);
+ } catch(Exception ex){
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "gMonth"});
+ }
+ }
+
+ /**
+ * Parses, validates and computes normalized version of gMonth object
+ *
+ * @param str The lexical representation of gMonth object --MM
+ * with possible time zone Z or (-),(+)hh:mm
+ * @return normalized date representation
+ * @exception SchemaDateTimeException Invalid lexical representation
+ */
+ protected DateTimeData parse(String str) throws SchemaDateTimeException{
+ DateTimeData date = new DateTimeData(str, this);
+ int len = str.length();
+
+ //set constants
+ date.year=YEAR;
+ date.day=DAY;
+ if (str.charAt(0)!='-' || str.charAt(1)!='-') {
+ throw new SchemaDateTimeException("Invalid format for gMonth: "+str);
+ }
+ int stop = 4;
+ date.month=parseInt(str,2,stop);
+
+ // REVISIT: allow both --MM and --MM-- now.
+ // need to remove the following 4 lines to disallow --MM--
+ // when the errata is offically in the rec.
+ if (str.length() >= stop+2 &&
+ str.charAt(stop) == '-' && str.charAt(stop+1) == '-') {
+ stop += 2;
+ }
+ if (stop < len) {
+ if (!isNextCharUTCSign(str, stop, len)) {
+ throw new SchemaDateTimeException ("Error in month parsing: "+str);
+ }
+ else {
+ getTimeZone(str, date, stop, len);
+ }
+ }
+ //validate and normalize
+ validateDateTime(date);
+
+ //save unnormalized values
+ saveUnnormalized(date);
+
+ if ( date.utc!=0 && date.utc!='Z' ) {
+ normalize(date);
+ }
+ date.position = 1;
+ return date;
+ }
+
+ /**
+ * Overwrite compare algorithm to optimize month comparison
+ *
+ * REVISIT: this one is lack of the third parameter: boolean strict, so it
+ * doesn't override the method in the base. But maybe this method
+ * is not correctly implemented, and I did encounter errors when
+ * trying to add the extra parameter. I'm leaving it as is. -SG
+ *
+ * @param date1
+ * @param date2
+ * @return less, greater, equal, indeterminate
+ */
+ /*protected short compareDates(DateTimeData date1, DateTimeData date2) {
+
+ if ( date1.utc==date2.utc ) {
+ return (short)((date1.month>=date2.month)?(date1.month>date2.month)?1:0:-1);
+ }
+
+ if ( date1.utc=='Z' || date2.utc=='Z' ) {
+
+ if ( date1.month==date2.month ) {
+ //--05--Z and --05--
+ return INDETERMINATE;
+ }
+ if ( (date1.month+1 == date2.month || date1.month-1 == date2.month) ) {
+ //--05--Z and (--04-- or --05--)
+ //REVISIT: should this case be less than or equal?
+ // maxExclusive should fail but what about maxInclusive
+ //
+ return INDETERMINATE;
+ }
+ }
+
+ if ( date1.month datatype (W3C Schema 1.1)
+ *
+ * @xerces.experimental
+ *
+ * @author Ankit Pasricha, IBM
+ *
+ * @version $Id$
+ */
+class PrecisionDecimalDV extends TypeValidator {
+
+ static class XPrecisionDecimal {
+
+ // sign: 0 for absent; 1 for positive values; -1 for negative values (except in case of INF, -INF)
+ int sign = 1;
+ // total digits. >= 1
+ int totalDigits = 0;
+ // integer digits when sign != 0
+ int intDigits = 0;
+ // fraction digits when sign != 0
+ int fracDigits = 0;
+ //precision
+ //int precision = 0;
+ // the string representing the integer part
+ String ivalue = "";
+ // the string representing the fraction part
+ String fvalue = "";
+
+ int pvalue = 0;
+
+
+ XPrecisionDecimal(String content) throws NumberFormatException {
+ if(content.equals("NaN")) {
+ ivalue = content;
+ sign = 0;
+ }
+ if(content.equals("+INF") || content.equals("INF") || content.equals("-INF")) {
+ ivalue = content.charAt(0) == '+' ? content.substring(1) : content;
+ return;
+ }
+ initD(content);
+ }
+
+ void initD(String content) throws NumberFormatException {
+ int len = content.length();
+ if (len == 0)
+ throw new NumberFormatException();
+
+ // these 4 variables are used to indicate where the integre/fraction
+ // parts start/end.
+ int intStart = 0, intEnd = 0, fracStart = 0, fracEnd = 0;
+
+ // Deal with leading sign symbol if present
+ if (content.charAt(0) == '+') {
+ // skip '+', so intStart should be 1
+ intStart = 1;
+ }
+ else if (content.charAt(0) == '-') {
+ intStart = 1;
+ sign = -1;
+ }
+
+ // skip leading zeroes in integer part
+ int actualIntStart = intStart;
+ while (actualIntStart < len && content.charAt(actualIntStart) == '0') {
+ actualIntStart++;
+ }
+
+ // Find the ending position of the integer part
+ for (intEnd = actualIntStart; intEnd < len && TypeValidator.isDigit(content.charAt(intEnd)); intEnd++);
+
+ // Not reached the end yet
+ if (intEnd < len) {
+ // the remaining part is not ".DDD" or "EDDD" or "eDDD", error
+ if (content.charAt(intEnd) != '.' && content.charAt(intEnd) != 'E' && content.charAt(intEnd) != 'e')
+ throw new NumberFormatException();
+
+ if(content.charAt(intEnd) == '.') {
+ // fraction part starts after '.', and ends at the end of the input
+ fracStart = intEnd + 1;
+
+ // find location of E or e (if present)
+ // Find the ending position of the fracion part
+ for (fracEnd = fracStart;
+ fracEnd < len && TypeValidator.isDigit(content.charAt(fracEnd));
+ fracEnd++);
+ }
+ else {
+ pvalue = Integer.parseInt(content.substring(intEnd + 1, len));
+ }
+ }
+
+ // no integer part, no fraction part, error.
+ if (intStart == intEnd && fracStart == fracEnd)
+ throw new NumberFormatException();
+
+ // ignore trailing zeroes in fraction part
+ /*while (fracEnd > fracStart && content.charAt(fracEnd-1) == '0') {
+ fracEnd--;
+ }*/
+
+ // check whether there is non-digit characters in the fraction part
+ for (int fracPos = fracStart; fracPos < fracEnd; fracPos++) {
+ if (!TypeValidator.isDigit(content.charAt(fracPos)))
+ throw new NumberFormatException();
+ }
+
+ intDigits = intEnd - actualIntStart;
+ fracDigits = fracEnd - fracStart;
+
+ if (intDigits > 0) {
+ ivalue = content.substring(actualIntStart, intEnd);
+ }
+
+ if (fracDigits > 0) {
+ fvalue = content.substring(fracStart, fracEnd);
+ if(fracEnd < len) {
+ pvalue = Integer.parseInt(content.substring(fracEnd + 1, len));
+ }
+ }
+ totalDigits = intDigits + fracDigits;
+ }
+
+
+ public boolean equals(Object val) {
+ if (val == this)
+ return true;
+
+ if (!(val instanceof XPrecisionDecimal))
+ return false;
+ XPrecisionDecimal oval = (XPrecisionDecimal)val;
+
+ return this.compareTo(oval) == EQUAL;
+ }
+
+ /**
+ * @return
+ */
+ private int compareFractionalPart(XPrecisionDecimal oval) {
+ if(fvalue.equals(oval.fvalue))
+ return EQUAL;
+
+ StringBuffer temp1 = new StringBuffer(fvalue);
+ StringBuffer temp2 = new StringBuffer(oval.fvalue);
+
+ truncateTrailingZeros(temp1, temp2);
+ return temp1.toString().compareTo(temp2.toString());
+ }
+
+ private void truncateTrailingZeros(StringBuffer fValue, StringBuffer otherFValue) {
+ for(int i = fValue.length() - 1;i >= 0; i--)
+ if(fValue.charAt(i) == '0')
+ fValue.deleteCharAt(i);
+ else
+ break;
+
+ for(int i = otherFValue.length() - 1;i >= 0; i--)
+ if(otherFValue.charAt(i) == '0')
+ otherFValue.deleteCharAt(i);
+ else
+ break;
+ }
+
+ public int compareTo(XPrecisionDecimal val) {
+
+ // seen NaN
+ if(sign == 0)
+ return INDETERMINATE;
+
+ //INF is greater than everything and equal to itself
+ if(ivalue.equals("INF") || val.ivalue.equals("INF")) {
+ if(ivalue.equals(val.ivalue))
+ return EQUAL;
+ else if(ivalue.equals("INF"))
+ return GREATER_THAN;
+ return LESS_THAN;
+ }
+
+ //-INF is smaller than everything and equal itself
+ if(ivalue.equals("-INF") || val.ivalue.equals("-INF")) {
+ if(ivalue.equals(val.ivalue))
+ return EQUAL;
+ else if(ivalue.equals("-INF"))
+ return LESS_THAN;
+ return GREATER_THAN;
+ }
+
+ if (sign != val.sign)
+ return sign > val.sign ? GREATER_THAN : LESS_THAN;
+
+ return sign * compare(val);
+ }
+
+ // To enable comparison - the exponent part of the decimal will be limited
+ // to the max value of int.
+ private int compare(XPrecisionDecimal val) {
+
+ if(pvalue != 0 || val.pvalue != 0) {
+ if(pvalue == val.pvalue)
+ return intComp(val);
+ else {
+
+ if(intDigits + pvalue != val.intDigits + val.pvalue)
+ return intDigits + pvalue > val.intDigits + val.pvalue ? GREATER_THAN : LESS_THAN;
+
+ //otherwise the 2 combined values are the same
+ if(pvalue > val.pvalue) {
+ int expDiff = pvalue - val.pvalue;
+ StringBuffer buffer = new StringBuffer(ivalue);
+ StringBuffer fbuffer = new StringBuffer(fvalue);
+ for(int i = 0;i < expDiff; i++) {
+ if(i < fracDigits) {
+ buffer.append(fvalue.charAt(i));
+ fbuffer.deleteCharAt(i);
+ }
+ else
+ buffer.append('0');
+ }
+ return compareDecimal(buffer.toString(), val.ivalue, fbuffer.toString(), val.fvalue);
+ }
+ else {
+ int expDiff = val.pvalue - pvalue;
+ StringBuffer buffer = new StringBuffer(val.ivalue);
+ StringBuffer fbuffer = new StringBuffer(val.fvalue);
+ for(int i = 0;i < expDiff; i++) {
+ if(i < val.fracDigits) {
+ buffer.append(val.fvalue.charAt(i));
+ fbuffer.deleteCharAt(i);
+ }
+ else
+ buffer.append('0');
+ }
+ return compareDecimal(ivalue, buffer.toString(), fvalue, fbuffer.toString());
+ }
+ }
+ }
+ else {
+ return intComp(val);
+ }
+ }
+
+ /**
+ * @param val
+ * @return
+ */
+ private int intComp(XPrecisionDecimal val) {
+ if (intDigits != val.intDigits)
+ return intDigits > val.intDigits ? GREATER_THAN : LESS_THAN;
+
+ return compareDecimal(ivalue, val.ivalue, fvalue, val.fvalue);
+ }
+
+ /**
+ * @param val
+ * @return
+ */
+ private int compareDecimal(String iValue, String fValue, String otherIValue, String otherFValue) {
+ int ret = iValue.compareTo(otherIValue);
+ if (ret != 0)
+ return ret > 0 ? GREATER_THAN : LESS_THAN;
+
+ if(fValue.equals(otherFValue))
+ return EQUAL;
+
+ StringBuffer temp1=new StringBuffer(fValue);
+ StringBuffer temp2=new StringBuffer(otherFValue);
+
+ truncateTrailingZeros(temp1, temp2);
+ ret = temp1.toString().compareTo(temp2.toString());
+ return ret == 0 ? EQUAL : (ret > 0 ? GREATER_THAN : LESS_THAN);
+ }
+
+ private String canonical;
+
+ public synchronized String toString() {
+ if (canonical == null) {
+ makeCanonical();
+ }
+ return canonical;
+ }
+
+ private void makeCanonical() {
+ // REVISIT: to be determined by working group
+ canonical = "TBD by Working Group";
+ }
+
+ /**
+ * @param decimal
+ * @return
+ */
+ public boolean isIdentical(XPrecisionDecimal decimal) {
+ if(ivalue.equals(decimal.ivalue) && (ivalue.equals("INF") || ivalue.equals("-INF") || ivalue.equals("NaN")))
+ return true;
+
+ if(sign == decimal.sign && intDigits == decimal.intDigits && fracDigits == decimal.fracDigits && pvalue == decimal.pvalue
+ && ivalue.equals(decimal.ivalue) && fvalue.equals(decimal.fvalue))
+ return true;
+ return false;
+ }
+
+ }
+ /* (non-Javadoc)
+ * @see org.apache.xerces.impl.dv.xs.TypeValidator#getAllowedFacets()
+ */
+ public short getAllowedFacets() {
+ return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE | XSSimpleTypeDecl.FACET_TOTALDIGITS | XSSimpleTypeDecl.FACET_FRACTIONDIGITS);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.impl.dv.xs.TypeValidator#getActualValue(java.lang.String, org.apache.xerces.impl.dv.ValidationContext)
+ */
+ public Object getActualValue(String content, ValidationContext context)
+ throws InvalidDatatypeValueException {
+ try {
+ return new XPrecisionDecimal(content);
+ } catch (NumberFormatException nfe) {
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "precisionDecimal"});
+ }
+ }
+
+ public int compare(Object value1, Object value2) {
+ return ((XPrecisionDecimal)value1).compareTo((XPrecisionDecimal)value2);
+ }
+
+ public int getFractionDigits(Object value) {
+ return ((XPrecisionDecimal)value).fracDigits;
+ }
+
+ public int getTotalDigits(Object value) {
+ return ((XPrecisionDecimal)value).totalDigits;
+ }
+
+ public boolean isIdentical(Object value1, Object value2) {
+ if(!(value2 instanceof XPrecisionDecimal) || !(value1 instanceof XPrecisionDecimal))
+ return false;
+ return ((XPrecisionDecimal)value1).isIdentical((XPrecisionDecimal)value2);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/QNameDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/QNameDV.java
new file mode 100644
index 0000000..1ea2560
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/QNameDV.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xs.datatypes.XSQName;
+
+/**
+ * Represent the schema type "QName" and "NOTATION"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class QNameDV extends TypeValidator {
+
+ private static final String EMPTY_STRING = "".intern();
+
+ public short getAllowedFacets() {
+ return (XSSimpleTypeDecl.FACET_LENGTH | XSSimpleTypeDecl.FACET_MINLENGTH | XSSimpleTypeDecl.FACET_MAXLENGTH | XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_ENUMERATION | XSSimpleTypeDecl.FACET_WHITESPACE);
+ }
+
+ public Object getActualValue(String content, ValidationContext context)
+ throws InvalidDatatypeValueException {
+
+ // "prefix:localpart" or "localpart"
+ // get prefix and local part out of content
+ String prefix, localpart;
+ int colonptr = content.indexOf(":");
+ if (colonptr > 0) {
+ prefix = context.getSymbol(content.substring(0,colonptr));
+ localpart = content.substring(colonptr+1);
+ } else {
+ prefix = EMPTY_STRING;
+ localpart = content;
+ }
+
+ // both prefix (if any) a nd localpart must be valid NCName
+ if (prefix.length() > 0 && !XMLChar.isValidNCName(prefix))
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "QName"});
+
+ if(!XMLChar.isValidNCName(localpart))
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "QName"});
+
+ // resove prefix to a uri, report an error if failed
+ String uri = context.getURI(prefix);
+ if (prefix.length() > 0 && uri == null)
+ throw new InvalidDatatypeValueException("UndeclaredPrefix", new Object[]{content, prefix});
+
+ return new XQName(prefix, context.getSymbol(localpart), context.getSymbol(content), uri);
+
+ }
+
+ // REVISIT: qname and notation shouldn't support length facets.
+ // now we just return the length of the rawname
+ public int getDataLength(Object value) {
+ return ((XQName)value).rawname.length();
+ }
+
+ /**
+ * represent QName data
+ */
+ private static final class XQName extends QName implements XSQName {
+ /** Constructs a QName with the specified values. */
+ public XQName(String prefix, String localpart, String rawname, String uri) {
+ setValues(prefix, localpart, rawname, uri);
+ } // (String,String,String,String)
+
+ /** Returns true if the two objects are equal. */
+ public boolean equals(Object object) {
+ if (object instanceof QName) {
+ QName qname = (QName)object;
+ return uri == qname.uri && localpart == qname.localpart;
+ }
+ return false;
+ } // equals(Object):boolean
+
+ public String toString() {
+ return rawname;
+ }
+ public javax.xml.namespace.QName getJAXPQName() {
+ return new javax.xml.namespace.QName(uri, localpart, prefix);
+ }
+ public QName getXNIQName() {
+ return this;
+ }
+ }
+} // class QNameDVDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/SchemaDVFactoryImpl.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/SchemaDVFactoryImpl.java
new file mode 100644
index 0000000..09a1d60
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/SchemaDVFactoryImpl.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.XSSimpleType;
+import org.apache.xerces.util.SymbolHash;
+
+/**
+ * the factory to create/return built-in schema 1.0 DVs and create user-defined DVs
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ * @author Khaled Noaman, IBM
+ *
+ * @version $Id$
+ */
+public class SchemaDVFactoryImpl extends BaseSchemaDVFactory {
+
+ static final SymbolHash fBuiltInTypes = new SymbolHash();
+
+ static {
+ createBuiltInTypes();
+ }
+
+ // create all built-in types
+ static void createBuiltInTypes() {
+ createBuiltInTypes(fBuiltInTypes, XSSimpleTypeDecl.fAnySimpleType);
+
+ // TODO: move specific 1.0 DV implementation from base
+ } //createBuiltInTypes()
+
+ /**
+ * Get a built-in simple type of the given name
+ * REVISIT: its still not decided within the Schema WG how to define the
+ * ur-types and if all simple types should be derived from a
+ * complex type, so as of now we ignore the fact that anySimpleType
+ * is derived from anyType, and pass 'null' as the base of
+ * anySimpleType. It needs to be changed as per the decision taken.
+ *
+ * @param name the name of the datatype
+ * @return the datatype validator of the given name
+ */
+ public XSSimpleType getBuiltInType(String name) {
+ return (XSSimpleType)fBuiltInTypes.get(name);
+ }
+
+ /**
+ * get all built-in simple types, which are stored in a hashtable keyed by
+ * the name
+ *
+ * @return a hashtable which contains all built-in simple types
+ */
+ public SymbolHash getBuiltInTypes() {
+ return (SymbolHash)fBuiltInTypes.makeClone();
+ }
+
+}//SchemaDVFactoryImpl
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/SchemaDateTimeException.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/SchemaDateTimeException.java
new file mode 100644
index 0000000..7d0d6fd
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/SchemaDateTimeException.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class SchemaDateTimeException extends RuntimeException {
+
+ /** Serialization version. */
+ static final long serialVersionUID = -8520832235337769040L;
+
+ public SchemaDateTimeException () {
+ super();
+ }
+
+ public SchemaDateTimeException (String s) {
+ super (s);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/StringDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/StringDV.java
new file mode 100644
index 0000000..5436151
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/StringDV.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Represent the schema type "string"
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class StringDV extends TypeValidator {
+
+ public short getAllowedFacets(){
+ return (XSSimpleTypeDecl.FACET_LENGTH | XSSimpleTypeDecl.FACET_MINLENGTH | XSSimpleTypeDecl.FACET_MAXLENGTH | XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_ENUMERATION | XSSimpleTypeDecl.FACET_WHITESPACE );
+ }
+
+ public Object getActualValue(String content, ValidationContext context)
+ throws InvalidDatatypeValueException {
+ return content;
+ }
+
+} // class StringDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/TimeDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/TimeDV.java
new file mode 100644
index 0000000..10d4880
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/TimeDV.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Validator for <time> datatype (W3C Schema Datatypes)
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani
+ * @author Gopal Sharma, SUN Microsystem Inc.
+ *
+ * @version $Id$
+ */
+public class TimeDV extends AbstractDateTimeDV {
+
+ /**
+ * Convert a string to a compiled form
+ *
+ * @param content The lexical representation of time
+ * @return a valid and normalized time object
+ */
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException{
+ try{
+ return parse(content);
+ } catch(Exception ex){
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "time"});
+ }
+ }
+
+ /**
+ * Parses, validates and computes normalized version of time object
+ *
+ * @param str The lexical representation of time object hh:mm:ss.sss
+ * with possible time zone Z or (-),(+)hh:mm
+ * Pattern: "(\\d\\d):(\\d\\d):(\\d\\d)(\\.(\\d)*)?(Z|(([-+])(\\d\\d)(:(\\d\\d))?))?")
+ * @return normalized time representation
+ * @exception SchemaDateTimeException Invalid lexical representation
+ */
+ protected DateTimeData parse(String str) throws SchemaDateTimeException{
+ DateTimeData date = new DateTimeData(str, this);
+ int len = str.length();
+
+ // time
+ // initialize to default values
+ date.year=YEAR;
+ date.month=MONTH;
+ date.day=15;
+ getTime(str, 0, len, date);
+
+ //validate and normalize
+
+ validateDateTime(date);
+
+ //save unnormalized values
+ saveUnnormalized(date);
+
+ if ( date.utc!=0 && date.utc != 'Z') {
+ normalize(date);
+ date.day = 15;
+ }
+ date.position = 2;
+ return date;
+ }
+
+ /**
+ * Converts time object representation to String
+ *
+ * @param date time object
+ * @return lexical representation of time: hh:mm:ss.sss with an optional time zone sign
+ */
+ protected String dateToString(DateTimeData date) {
+ StringBuffer message = new StringBuffer(16);
+ append(message, date.hour, 2);
+ message.append(':');
+ append(message, date.minute, 2);
+ message.append(':');
+ append(message, date.second);
+
+ append(message, (char)date.utc, 0);
+ return message.toString();
+ }
+
+ protected XMLGregorianCalendar getXMLGregorianCalendar(DateTimeData date) {
+ return datatypeFactory.newXMLGregorianCalendar(null, DatatypeConstants.FIELD_UNDEFINED,
+ DatatypeConstants.FIELD_UNDEFINED, date.unNormHour, date.unNormMinute,
+ (int)date.unNormSecond, date.unNormSecond != 0 ? getFractionalSecondsAsBigDecimal(date) : null,
+ date.hasTimeZone() ? (date.timezoneHr * 60 + date.timezoneMin) : DatatypeConstants.FIELD_UNDEFINED);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/TypeValidator.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/TypeValidator.java
new file mode 100644
index 0000000..2a645a2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/TypeValidator.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.XMLChar;
+
+/**
+ * All primitive types plus ID/IDREF/ENTITY/INTEGER are derived from this abstract
+ * class. It provides extra information XSSimpleTypeDecl requires from each
+ * type: allowed facets, converting String to actual value, check equality,
+ * comparison, etc.
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public abstract class TypeValidator {
+
+ private static final boolean USE_CODE_POINT_COUNT_FOR_STRING_LENGTH = AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ try {
+ return Boolean.getBoolean("org.apache.xerces.impl.dv.xs.useCodePointCountForStringLength") ? Boolean.TRUE : Boolean.FALSE;
+ }
+ catch (SecurityException ex) {}
+ return Boolean.FALSE;
+ }}) == Boolean.TRUE;
+
+ // which facets are allowed for this type
+ public abstract short getAllowedFacets();
+
+ // convert a string to an actual value. for example,
+ // for number types (decimal, double, float, and types derived from them),
+ // get the BigDecimal, Double, Flout object.
+ // for some types (string and derived), they just return the string itself
+ public abstract Object getActualValue(String content, ValidationContext context)
+ throws InvalidDatatypeValueException;
+
+ // for ID/IDREF/ENTITY types, do some extra checking after the value is
+ // checked to be valid with respect to both lexical representation and
+ // facets
+ public void checkExtraRules(Object value, ValidationContext context) throws InvalidDatatypeValueException {
+ }
+
+ // the following methods might not be supported by every DV.
+ // but XSSimpleTypeDecl should know which type supports which methods,
+ // and it's an *internal* error if a method is called on a DV that
+ // doesn't support it.
+
+ //order constants
+ public static final short LESS_THAN = -1;
+ public static final short EQUAL = 0;
+ public static final short GREATER_THAN = 1;
+ public static final short INDETERMINATE = 2;
+
+ // where there is distinction between identity and equality, this method
+ // will be overwritten
+ // checks whether the two values are identical; for ex, this distinguishes
+ // -0.0 from 0.0
+ public boolean isIdentical (Object value1, Object value2) {
+ return value1.equals(value2);
+ }
+
+ // check the order relation between the two values
+ // the parameters are in compiled form (from getActualValue)
+ public int compare(Object value1, Object value2) {
+ return -1;
+ }
+
+ // get the length of the value
+ // the parameters are in compiled form (from getActualValue)
+ public int getDataLength(Object value) {
+ if (value instanceof String) {
+ final String str = (String)value;
+ if (!USE_CODE_POINT_COUNT_FOR_STRING_LENGTH) {
+ return str.length();
+ }
+ return getCodePointLength(str);
+ }
+ return -1;
+ }
+
+ // get the number of digits of the value
+ // the parameters are in compiled form (from getActualValue)
+ public int getTotalDigits(Object value) {
+ return -1;
+ }
+
+ // get the number of fraction digits of the value
+ // the parameters are in compiled form (from getActualValue)
+ public int getFractionDigits(Object value) {
+ return -1;
+ }
+
+ // Returns the length of the string in Unicode code points.
+ private int getCodePointLength(String value) {
+ // Count the number of surrogate pairs, and subtract them from
+ // the total length.
+ final int len = value.length();
+ int surrogatePairCount = 0;
+ for (int i = 0; i < len - 1; ++i) {
+ if (XMLChar.isHighSurrogate(value.charAt(i))) {
+ if (XMLChar.isLowSurrogate(value.charAt(++i))) {
+ ++surrogatePairCount;
+ }
+ else {
+ --i;
+ }
+ }
+ }
+ return len - surrogatePairCount;
+ }
+
+ // check whether the character is in the range 0x30 ~ 0x39
+ public static final boolean isDigit(char ch) {
+ return ch >= '0' && ch <= '9';
+ }
+
+ // if the character is in the range 0x30 ~ 0x39, return its int value (0~9),
+ // otherwise, return -1
+ public static final int getDigit(char ch) {
+ return isDigit(ch) ? ch - '0' : -1;
+ }
+
+} // interface TypeValidator
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/UnionDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/UnionDV.java
new file mode 100644
index 0000000..89f63ca
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/UnionDV.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Represent the schema union types
+ *
+ * @xerces.internal
+ *
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ * @author Sandy Gao, IBM
+ *
+ * @version $Id$
+ */
+public class UnionDV extends TypeValidator{
+
+ public short getAllowedFacets(){
+ return (XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_ENUMERATION );
+ }
+
+ // this method should never be called: XSSimpleTypeDecl is responsible for
+ // calling the member types for the convertion
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException{
+ return content;
+ }
+
+} // class UnionDV
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/XSSimpleTypeDecl.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/XSSimpleTypeDecl.java
new file mode 100644
index 0000000..0e75e13
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/XSSimpleTypeDecl.java
@@ -0,0 +1,3487 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import java.math.BigInteger;
+import java.util.AbstractList;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.impl.dv.DatatypeException;
+import org.apache.xerces.impl.dv.InvalidDatatypeFacetException;
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidatedInfo;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.impl.dv.XSFacets;
+import org.apache.xerces.impl.dv.XSSimpleType;
+import org.apache.xerces.impl.xpath.regex.RegularExpression;
+import org.apache.xerces.impl.xs.SchemaSymbols;
+import org.apache.xerces.impl.xs.util.ObjectListImpl;
+import org.apache.xerces.impl.xs.util.ShortListImpl;
+import org.apache.xerces.impl.xs.util.StringListImpl;
+import org.apache.xerces.impl.xs.util.XSObjectListImpl;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xs.ShortList;
+import org.apache.xerces.xs.StringList;
+import org.apache.xerces.xs.XSAnnotation;
+import org.apache.xerces.xs.XSConstants;
+import org.apache.xerces.xs.XSFacet;
+import org.apache.xerces.xs.XSMultiValueFacet;
+import org.apache.xerces.xs.XSNamespaceItem;
+import org.apache.xerces.xs.XSObject;
+import org.apache.xerces.xs.XSObjectList;
+import org.apache.xerces.xs.XSSimpleTypeDefinition;
+import org.apache.xerces.xs.XSTypeDefinition;
+import org.apache.xerces.xs.datatypes.ObjectList;
+import org.w3c.dom.TypeInfo;
+
+/**
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ * @author Neeraj Bajaj, Sun Microsystems, inc.
+ *
+ * @version $Id$
+ */
+public class XSSimpleTypeDecl implements XSSimpleType, TypeInfo {
+
+ protected static final short DV_STRING = PRIMITIVE_STRING;
+ protected static final short DV_BOOLEAN = PRIMITIVE_BOOLEAN;
+ protected static final short DV_DECIMAL = PRIMITIVE_DECIMAL;
+ protected static final short DV_FLOAT = PRIMITIVE_FLOAT;
+ protected static final short DV_DOUBLE = PRIMITIVE_DOUBLE;
+ protected static final short DV_DURATION = PRIMITIVE_DURATION;
+ protected static final short DV_DATETIME = PRIMITIVE_DATETIME;
+ protected static final short DV_TIME = PRIMITIVE_TIME;
+ protected static final short DV_DATE = PRIMITIVE_DATE;
+ protected static final short DV_GYEARMONTH = PRIMITIVE_GYEARMONTH;
+ protected static final short DV_GYEAR = PRIMITIVE_GYEAR;
+ protected static final short DV_GMONTHDAY = PRIMITIVE_GMONTHDAY;
+ protected static final short DV_GDAY = PRIMITIVE_GDAY;
+ protected static final short DV_GMONTH = PRIMITIVE_GMONTH;
+ protected static final short DV_HEXBINARY = PRIMITIVE_HEXBINARY;
+ protected static final short DV_BASE64BINARY = PRIMITIVE_BASE64BINARY;
+ protected static final short DV_ANYURI = PRIMITIVE_ANYURI;
+ protected static final short DV_QNAME = PRIMITIVE_QNAME;
+ protected static final short DV_PRECISIONDECIMAL = PRIMITIVE_PRECISIONDECIMAL;
+ protected static final short DV_NOTATION = PRIMITIVE_NOTATION;
+
+ protected static final short DV_ANYSIMPLETYPE = 0;
+ protected static final short DV_ID = DV_NOTATION + 1;
+ protected static final short DV_IDREF = DV_NOTATION + 2;
+ protected static final short DV_ENTITY = DV_NOTATION + 3;
+ protected static final short DV_INTEGER = DV_NOTATION + 4;
+ protected static final short DV_LIST = DV_NOTATION + 5;
+ protected static final short DV_UNION = DV_NOTATION + 6;
+ protected static final short DV_YEARMONTHDURATION = DV_NOTATION + 7;
+ protected static final short DV_DAYTIMEDURATION = DV_NOTATION + 8;
+ protected static final short DV_ANYATOMICTYPE = DV_NOTATION + 9;
+
+ private static final TypeValidator[] gDVs = {
+ new AnySimpleDV(),
+ new StringDV(),
+ new BooleanDV(),
+ new DecimalDV(),
+ new FloatDV(),
+ new DoubleDV(),
+ new DurationDV(),
+ new DateTimeDV(),
+ new TimeDV(),
+ new DateDV(),
+ new YearMonthDV(),
+ new YearDV(),
+ new MonthDayDV(),
+ new DayDV(),
+ new MonthDV(),
+ new HexBinaryDV(),
+ new Base64BinaryDV(),
+ new AnyURIDV(),
+ new QNameDV(),
+ new PrecisionDecimalDV(), // XML Schema 1.1 type
+ new QNameDV(), // notation use the same one as qname
+ new IDDV(),
+ new IDREFDV(),
+ new EntityDV(),
+ new IntegerDV(),
+ new ListDV(),
+ new UnionDV(),
+ new YearMonthDurationDV(), // XML Schema 1.1 type
+ new DayTimeDurationDV(), // XML Schema 1.1 type
+ new AnyAtomicDV() // XML Schema 1.1 type
+ };
+
+ static final short NORMALIZE_NONE = 0;
+ static final short NORMALIZE_TRIM = 1;
+ static final short NORMALIZE_FULL = 2;
+ static final short[] fDVNormalizeType = {
+ NORMALIZE_NONE, //AnySimpleDV(),
+ NORMALIZE_FULL, //StringDV(),
+ NORMALIZE_TRIM, //BooleanDV(),
+ NORMALIZE_TRIM, //DecimalDV(),
+ NORMALIZE_TRIM, //FloatDV(),
+ NORMALIZE_TRIM, //DoubleDV(),
+ NORMALIZE_TRIM, //DurationDV(),
+ NORMALIZE_TRIM, //DateTimeDV(),
+ NORMALIZE_TRIM, //TimeDV(),
+ NORMALIZE_TRIM, //DateDV(),
+ NORMALIZE_TRIM, //YearMonthDV(),
+ NORMALIZE_TRIM, //YearDV(),
+ NORMALIZE_TRIM, //MonthDayDV(),
+ NORMALIZE_TRIM, //DayDV(),
+ NORMALIZE_TRIM, //MonthDV(),
+ NORMALIZE_TRIM, //HexBinaryDV(),
+ NORMALIZE_NONE, //Base64BinaryDV(), // Base64 know how to deal with spaces
+ NORMALIZE_TRIM, //AnyURIDV(),
+ NORMALIZE_TRIM, //QNameDV(),
+ NORMALIZE_TRIM, //PrecisionDecimalDV() (Schema 1.1)
+ NORMALIZE_TRIM, //QNameDV(), // notation
+ NORMALIZE_TRIM, //IDDV(),
+ NORMALIZE_TRIM, //IDREFDV(),
+ NORMALIZE_TRIM, //EntityDV(),
+ NORMALIZE_TRIM, //IntegerDV(),
+ NORMALIZE_FULL, //ListDV(),
+ NORMALIZE_NONE, //UnionDV(),
+ NORMALIZE_TRIM, //YearMonthDurationDV() (Schema 1.1)
+ NORMALIZE_TRIM, //DayTimeDurationDV() (Schema 1.1)
+ NORMALIZE_NONE, //AnyAtomicDV() (Schema 1.1)
+ };
+
+ static final short SPECIAL_PATTERN_NONE = 0;
+ static final short SPECIAL_PATTERN_NMTOKEN = 1;
+ static final short SPECIAL_PATTERN_NAME = 2;
+ static final short SPECIAL_PATTERN_NCNAME = 3;
+
+ static final String[] SPECIAL_PATTERN_STRING = {
+ "NONE", "NMTOKEN", "Name", "NCName"
+ };
+
+ static final String[] WS_FACET_STRING = {
+ "preserve", "replace", "collapse"
+ };
+
+ static final String URI_SCHEMAFORSCHEMA = "http://www.w3.org/2001/XMLSchema";
+ static final String ANY_TYPE = "anyType";
+
+ // XML Schema 1.1 type constants
+ public static final short YEARMONTHDURATION_DT = 46;
+ public static final short DAYTIMEDURATION_DT = 47;
+ public static final short PRECISIONDECIMAL_DT = 48;
+ public static final short ANYATOMICTYPE_DT = 49;
+
+ // DOM Level 3 TypeInfo Derivation Method constants
+ static final int DERIVATION_ANY = 0;
+ static final int DERIVATION_RESTRICTION = 1;
+ static final int DERIVATION_EXTENSION = 2;
+ static final int DERIVATION_UNION = 4;
+ static final int DERIVATION_LIST = 8;
+
+ static final ValidationContext fEmptyContext = new ValidationContext() {
+ public boolean needFacetChecking() {
+ return true;
+ }
+ public boolean needExtraChecking() {
+ return false;
+ }
+ public boolean needToNormalize() {
+ return true;
+ }
+ public boolean useNamespaces () {
+ return true;
+ }
+ public boolean isEntityDeclared (String name) {
+ return false;
+ }
+ public boolean isEntityUnparsed (String name) {
+ return false;
+ }
+ public boolean isIdDeclared (String name) {
+ return false;
+ }
+ public void addId(String name) {
+ }
+ public void addIdRef(String name) {
+ }
+ public String getSymbol (String symbol) {
+ return symbol.intern();
+ }
+ public String getURI(String prefix) {
+ return null;
+ }
+ public Locale getLocale() {
+ return Locale.getDefault();
+ }
+ };
+
+ protected static TypeValidator[] getGDVs() {
+ return (TypeValidator[])gDVs.clone();
+ }
+ private TypeValidator[] fDVs = gDVs;
+ protected void setDVs(TypeValidator[] dvs) {
+ fDVs = dvs;
+ }
+
+ // this will be true if this is a static XSSimpleTypeDecl
+ // and hence must remain immutable (i.e., applyFacets
+ // may not be permitted to have any effect).
+ private boolean fIsImmutable = false;
+
+ private XSSimpleTypeDecl fItemType;
+ private XSSimpleTypeDecl[] fMemberTypes;
+ // The most specific built-in type kind.
+ private short fBuiltInKind;
+
+ private String fTypeName;
+ private String fTargetNamespace;
+ private short fFinalSet = 0;
+ private XSSimpleTypeDecl fBase;
+ private short fVariety = -1;
+ private short fValidationDV = -1;
+
+ private short fFacetsDefined = 0;
+ private short fFixedFacet = 0;
+
+ //for constraining facets
+ private short fWhiteSpace = 0;
+ private int fLength = -1;
+ private int fMinLength = -1;
+ private int fMaxLength = -1;
+ private int fTotalDigits = -1;
+ private int fFractionDigits = -1;
+ private Vector fPattern;
+ private Vector fPatternStr;
+ private ValidatedInfo[] fEnumeration;
+ private int fEnumerationSize;
+ private ShortList fEnumerationTypeList;
+ private ObjectList fEnumerationItemTypeList;
+ private StringList fLexicalPattern;
+ private StringList fLexicalEnumeration;
+ private ObjectList fActualEnumeration;
+ private Object fMaxInclusive;
+ private Object fMaxExclusive;
+ private Object fMinExclusive;
+ private Object fMinInclusive;
+
+ // annotations for constraining facets
+ public XSAnnotation lengthAnnotation;
+ public XSAnnotation minLengthAnnotation;
+ public XSAnnotation maxLengthAnnotation;
+ public XSAnnotation whiteSpaceAnnotation;
+ public XSAnnotation totalDigitsAnnotation;
+ public XSAnnotation fractionDigitsAnnotation;
+ public XSObjectListImpl patternAnnotations;
+ public XSObjectList enumerationAnnotations;
+ public XSAnnotation maxInclusiveAnnotation;
+ public XSAnnotation maxExclusiveAnnotation;
+ public XSAnnotation minInclusiveAnnotation;
+ public XSAnnotation minExclusiveAnnotation;
+
+ // facets as objects
+ private XSObjectListImpl fFacets;
+
+ // enumeration and pattern facets
+ private XSObjectListImpl fMultiValueFacets;
+
+ // simpleType annotations
+ private XSObjectList fAnnotations = null;
+
+ private short fPatternType = SPECIAL_PATTERN_NONE;
+
+ // for fundamental facets
+ private short fOrdered;
+ private boolean fFinite;
+ private boolean fBounded;
+ private boolean fNumeric;
+
+ // The namespace schema information item corresponding to the target namespace
+ // of the simple type definition, if it is globally declared; or null otherwise.
+ private XSNamespaceItem fNamespaceItem = null;
+
+ // default constructor
+ public XSSimpleTypeDecl(){}
+
+ //Create a new built-in primitive types (and id/idref/entity/integer/yearMonthDuration)
+ protected XSSimpleTypeDecl(XSSimpleTypeDecl base, String name, short validateDV,
+ short ordered, boolean bounded, boolean finite,
+ boolean numeric, boolean isImmutable, short builtInKind) {
+ fIsImmutable = isImmutable;
+ fBase = base;
+ fTypeName = name;
+ fTargetNamespace = URI_SCHEMAFORSCHEMA;
+ // To simplify the code for anySimpleType, we treat it as an atomic type
+ fVariety = VARIETY_ATOMIC;
+ fValidationDV = validateDV;
+ fFacetsDefined = FACET_WHITESPACE;
+ if (validateDV == DV_ANYSIMPLETYPE ||
+ validateDV == DV_ANYATOMICTYPE ||
+ validateDV == DV_STRING) {
+ fWhiteSpace = WS_PRESERVE;
+ }
+ else {
+ fWhiteSpace = WS_COLLAPSE;
+ fFixedFacet = FACET_WHITESPACE;
+ }
+ this.fOrdered = ordered;
+ this.fBounded = bounded;
+ this.fFinite = finite;
+ this.fNumeric = numeric;
+ fAnnotations = null;
+
+ // Specify the build in kind for this primitive type
+ fBuiltInKind = builtInKind;
+ }
+
+ //Create a new simple type for restriction for built-in types
+ protected XSSimpleTypeDecl(XSSimpleTypeDecl base, String name, String uri, short finalSet, boolean isImmutable,
+ XSObjectList annotations, short builtInKind) {
+ this(base, name, uri, finalSet, isImmutable, annotations);
+ // Specify the build in kind for this built-in type
+ fBuiltInKind = builtInKind;
+ }
+
+ //Create a new simple type for restriction.
+ protected XSSimpleTypeDecl(XSSimpleTypeDecl base, String name, String uri, short finalSet, boolean isImmutable,
+ XSObjectList annotations) {
+ fBase = base;
+ fTypeName = name;
+ fTargetNamespace = uri;
+ fFinalSet = finalSet;
+ fAnnotations = annotations;
+
+ fVariety = fBase.fVariety;
+ fValidationDV = fBase.fValidationDV;
+ switch (fVariety) {
+ case VARIETY_ATOMIC:
+ break;
+ case VARIETY_LIST:
+ fItemType = fBase.fItemType;
+ break;
+ case VARIETY_UNION:
+ fMemberTypes = fBase.fMemberTypes;
+ break;
+ }
+
+ // always inherit facets from the base.
+ // in case a type is created, but applyFacets is not called
+ fLength = fBase.fLength;
+ fMinLength = fBase.fMinLength;
+ fMaxLength = fBase.fMaxLength;
+ fPattern = fBase.fPattern;
+ fPatternStr = fBase.fPatternStr;
+ fEnumeration = fBase.fEnumeration;
+ fEnumerationSize = fBase.fEnumerationSize;
+ fWhiteSpace = fBase.fWhiteSpace;
+ fMaxExclusive = fBase.fMaxExclusive;
+ fMaxInclusive = fBase.fMaxInclusive;
+ fMinExclusive = fBase.fMinExclusive;
+ fMinInclusive = fBase.fMinInclusive;
+ fTotalDigits = fBase.fTotalDigits;
+ fFractionDigits = fBase.fFractionDigits;
+ fPatternType = fBase.fPatternType;
+ fFixedFacet = fBase.fFixedFacet;
+ fFacetsDefined = fBase.fFacetsDefined;
+
+ // always inherit facet annotations in case applyFacets is not called.
+ lengthAnnotation = fBase.lengthAnnotation;
+ minLengthAnnotation = fBase.minLengthAnnotation;
+ maxLengthAnnotation = fBase.maxLengthAnnotation;
+ patternAnnotations = fBase.patternAnnotations;
+ enumerationAnnotations = fBase.enumerationAnnotations;
+ whiteSpaceAnnotation = fBase.whiteSpaceAnnotation;
+ maxExclusiveAnnotation = fBase.maxExclusiveAnnotation;
+ maxInclusiveAnnotation = fBase.maxInclusiveAnnotation;
+ minExclusiveAnnotation = fBase.minExclusiveAnnotation;
+ minInclusiveAnnotation = fBase.minInclusiveAnnotation;
+ totalDigitsAnnotation = fBase.totalDigitsAnnotation;
+ fractionDigitsAnnotation = fBase.fractionDigitsAnnotation;
+
+ //we also set fundamental facets information in case applyFacets is not called.
+ calcFundamentalFacets();
+ fIsImmutable = isImmutable;
+
+ // Inherit from the base type
+ fBuiltInKind = base.fBuiltInKind;
+ }
+
+ //Create a new simple type for list.
+ protected XSSimpleTypeDecl(String name, String uri, short finalSet, XSSimpleTypeDecl itemType, boolean isImmutable,
+ XSObjectList annotations) {
+ fBase = fAnySimpleType;
+ fTypeName = name;
+ fTargetNamespace = uri;
+ fFinalSet = finalSet;
+ fAnnotations = annotations;
+
+ fVariety = VARIETY_LIST;
+ fItemType = (XSSimpleTypeDecl)itemType;
+ fValidationDV = DV_LIST;
+ fFacetsDefined = FACET_WHITESPACE;
+ fFixedFacet = FACET_WHITESPACE;
+ fWhiteSpace = WS_COLLAPSE;
+
+ //setting fundamental facets
+ calcFundamentalFacets();
+ fIsImmutable = isImmutable;
+
+ // Values of this type are lists
+ fBuiltInKind = XSConstants.LIST_DT;
+ }
+
+ //Create a new simple type for union.
+ protected XSSimpleTypeDecl(String name, String uri, short finalSet, XSSimpleTypeDecl[] memberTypes,
+ XSObjectList annotations) {
+ fBase = fAnySimpleType;
+ fTypeName = name;
+ fTargetNamespace = uri;
+ fFinalSet = finalSet;
+ fAnnotations = annotations;
+
+ fVariety = VARIETY_UNION;
+ fMemberTypes = memberTypes;
+ fValidationDV = DV_UNION;
+ // even for union, we set whitespace to something
+ // this will never be used, but we can use fFacetsDefined to check
+ // whether applyFacets() is allwwed: it's not allowed
+ // if fFacetsDefined != 0
+ fFacetsDefined = FACET_WHITESPACE;
+ fWhiteSpace = WS_COLLAPSE;
+
+ //setting fundamental facets
+ calcFundamentalFacets();
+ // none of the schema-defined types are unions, so just set
+ // fIsImmutable to false.
+ fIsImmutable = false;
+
+ // No value can be of this type, so it's unavailable.
+ fBuiltInKind = XSConstants.UNAVAILABLE_DT;
+ }
+
+ //set values for restriction.
+ protected XSSimpleTypeDecl setRestrictionValues(XSSimpleTypeDecl base, String name, String uri, short finalSet,
+ XSObjectList annotations) {
+ //decline to do anything if the object is immutable.
+ if(fIsImmutable) return null;
+ fBase = base;
+ fAnonymous = false;
+ fTypeName = name;
+ fTargetNamespace = uri;
+ fFinalSet = finalSet;
+ fAnnotations = annotations;
+
+ fVariety = fBase.fVariety;
+ fValidationDV = fBase.fValidationDV;
+ switch (fVariety) {
+ case VARIETY_ATOMIC:
+ break;
+ case VARIETY_LIST:
+ fItemType = fBase.fItemType;
+ break;
+ case VARIETY_UNION:
+ fMemberTypes = fBase.fMemberTypes;
+ break;
+ }
+
+ // always inherit facets from the base.
+ // in case a type is created, but applyFacets is not called
+ fLength = fBase.fLength;
+ fMinLength = fBase.fMinLength;
+ fMaxLength = fBase.fMaxLength;
+ fPattern = fBase.fPattern;
+ fPatternStr = fBase.fPatternStr;
+ fEnumeration = fBase.fEnumeration;
+ fEnumerationSize = fBase.fEnumerationSize;
+ fWhiteSpace = fBase.fWhiteSpace;
+ fMaxExclusive = fBase.fMaxExclusive;
+ fMaxInclusive = fBase.fMaxInclusive;
+ fMinExclusive = fBase.fMinExclusive;
+ fMinInclusive = fBase.fMinInclusive;
+ fTotalDigits = fBase.fTotalDigits;
+ fFractionDigits = fBase.fFractionDigits;
+ fPatternType = fBase.fPatternType;
+ fFixedFacet = fBase.fFixedFacet;
+ fFacetsDefined = fBase.fFacetsDefined;
+
+ //we also set fundamental facets information in case applyFacets is not called.
+ calcFundamentalFacets();
+
+ // Inherit from the base type
+ fBuiltInKind = base.fBuiltInKind;
+
+ return this;
+ }
+
+ //set values for list.
+ protected XSSimpleTypeDecl setListValues(String name, String uri, short finalSet, XSSimpleTypeDecl itemType,
+ XSObjectList annotations) {
+ //decline to do anything if the object is immutable.
+ if(fIsImmutable) return null;
+ fBase = fAnySimpleType;
+ fAnonymous = false;
+ fTypeName = name;
+ fTargetNamespace = uri;
+ fFinalSet = finalSet;
+ fAnnotations = annotations;
+
+ fVariety = VARIETY_LIST;
+ fItemType = (XSSimpleTypeDecl)itemType;
+ fValidationDV = DV_LIST;
+ fFacetsDefined = FACET_WHITESPACE;
+ fFixedFacet = FACET_WHITESPACE;
+ fWhiteSpace = WS_COLLAPSE;
+
+ //setting fundamental facets
+ calcFundamentalFacets();
+
+ // Values of this type are lists
+ fBuiltInKind = XSConstants.LIST_DT;
+
+ return this;
+ }
+
+ //set values for union.
+ protected XSSimpleTypeDecl setUnionValues(String name, String uri, short finalSet, XSSimpleTypeDecl[] memberTypes,
+ XSObjectList annotations) {
+ //decline to do anything if the object is immutable.
+ if(fIsImmutable) return null;
+ fBase = fAnySimpleType;
+ fAnonymous = false;
+ fTypeName = name;
+ fTargetNamespace = uri;
+ fFinalSet = finalSet;
+ fAnnotations = annotations;
+
+ fVariety = VARIETY_UNION;
+ fMemberTypes = memberTypes;
+ fValidationDV = DV_UNION;
+ // even for union, we set whitespace to something
+ // this will never be used, but we can use fFacetsDefined to check
+ // whether applyFacets() is allwwed: it's not allowed
+ // if fFacetsDefined != 0
+ fFacetsDefined = FACET_WHITESPACE;
+ fWhiteSpace = WS_COLLAPSE;
+
+ //setting fundamental facets
+ calcFundamentalFacets();
+
+ // No value can be of this type, so it's unavailable.
+ fBuiltInKind = XSConstants.UNAVAILABLE_DT;
+
+ return this;
+ }
+
+ public short getType () {
+ return XSConstants.TYPE_DEFINITION;
+ }
+
+ public short getTypeCategory () {
+ return SIMPLE_TYPE;
+ }
+
+ public String getName() {
+ return getAnonymous()?null:fTypeName;
+ }
+
+ public String getTypeName() {
+ return fTypeName;
+ }
+
+ public String getNamespace() {
+ return fTargetNamespace;
+ }
+
+ public short getFinal(){
+ return fFinalSet;
+ }
+
+ public boolean isFinal(short derivation) {
+ return (fFinalSet & derivation) != 0;
+ }
+
+ public XSTypeDefinition getBaseType(){
+ return fBase;
+ }
+
+ public boolean getAnonymous() {
+ return fAnonymous || (fTypeName == null);
+ }
+
+ public short getVariety(){
+ // for anySimpleType, return absent variaty
+ return fValidationDV == DV_ANYSIMPLETYPE ? VARIETY_ABSENT : fVariety;
+ }
+
+ public boolean isIDType(){
+ switch (fVariety) {
+ case VARIETY_ATOMIC:
+ return fValidationDV == DV_ID;
+ case VARIETY_LIST:
+ return fItemType.isIDType();
+ case VARIETY_UNION:
+ for (int i = 0; i < fMemberTypes.length; i++) {
+ if (fMemberTypes[i].isIDType())
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public short getWhitespace() throws DatatypeException{
+ if (fVariety == VARIETY_UNION) {
+ throw new DatatypeException("dt-whitespace", new Object[]{fTypeName});
+ }
+ return fWhiteSpace;
+ }
+
+ public short getPrimitiveKind() {
+ if (fVariety == VARIETY_ATOMIC && fValidationDV != DV_ANYSIMPLETYPE) {
+ if (fValidationDV == DV_ID || fValidationDV == DV_IDREF || fValidationDV == DV_ENTITY) {
+ return DV_STRING;
+ }
+ else if (fValidationDV == DV_INTEGER) {
+ return DV_DECIMAL;
+ }
+ else if (Constants.SCHEMA_1_1_SUPPORT && (fValidationDV == DV_YEARMONTHDURATION || fValidationDV == DV_DAYTIMEDURATION)) {
+ return DV_DURATION;
+ }
+ else {
+ return fValidationDV;
+ }
+ }
+ else {
+ // REVISIT: error situation. runtime exception?
+ return (short)0;
+ }
+ }
+
+ /**
+ * Returns the closest built-in type category this type represents or
+ * derived from. For example, if this simple type is a built-in derived
+ * type integer the INTEGER_DV is returned.
+ */
+ public short getBuiltInKind() {
+ return this.fBuiltInKind;
+ }
+
+ /**
+ * If variety is atomic the primitive type definition (a
+ * built-in primitive datatype definition or the simple ur-type
+ * definition) is available, otherwise null .
+ */
+ public XSSimpleTypeDefinition getPrimitiveType() {
+ if (fVariety == VARIETY_ATOMIC && fValidationDV != DV_ANYSIMPLETYPE) {
+ XSSimpleTypeDecl pri = this;
+ // recursively get base, until we reach anySimpleType
+ while (pri.fBase != fAnySimpleType)
+ pri = pri.fBase;
+ return pri;
+ }
+ else {
+ // REVISIT: error situation. runtime exception?
+ return null;
+ }
+ }
+
+ /**
+ * If variety is list the item type definition (an atomic or
+ * union simple type definition) is available, otherwise
+ * null .
+ */
+ public XSSimpleTypeDefinition getItemType() {
+ if (fVariety == VARIETY_LIST) {
+ return fItemType;
+ }
+ else {
+ // REVISIT: error situation. runtime exception?
+ return null;
+ }
+ }
+
+ /**
+ * If variety is union the list of member type definitions (a
+ * non-empty sequence of simple type definitions) is available,
+ * otherwise an empty XSObjectList .
+ */
+ public XSObjectList getMemberTypes() {
+ if (fVariety == VARIETY_UNION) {
+ return new XSObjectListImpl(fMemberTypes, fMemberTypes.length);
+ }
+ else {
+ return XSObjectListImpl.EMPTY_LIST;
+ }
+ }
+
+ /**
+ * If is chosen
+ */
+ public void applyFacets(XSFacets facets, short presentFacet, short fixedFacet, ValidationContext context)
+ throws InvalidDatatypeFacetException {
+ if (context == null) {
+ context = fEmptyContext;
+ }
+ applyFacets(facets, presentFacet, fixedFacet, SPECIAL_PATTERN_NONE, context);
+ }
+
+ /**
+ * built-in derived types by restriction
+ */
+ void applyFacets1(XSFacets facets, short presentFacet, short fixedFacet) {
+
+ try {
+ applyFacets(facets, presentFacet, fixedFacet, SPECIAL_PATTERN_NONE, fDummyContext);
+ } catch (InvalidDatatypeFacetException e) {
+ // should never gets here, internel error
+ throw new RuntimeException("internal error");
+ }
+ // we've now applied facets; so lock this object:
+ fIsImmutable = true;
+ }
+
+ /**
+ * built-in derived types by restriction
+ */
+ void applyFacets1(XSFacets facets, short presentFacet, short fixedFacet, short patternType) {
+
+ try {
+ applyFacets(facets, presentFacet, fixedFacet, patternType, fDummyContext);
+ } catch (InvalidDatatypeFacetException e) {
+ // should never gets here, internel error
+ throw new RuntimeException("internal error");
+ }
+ // we've now applied facets; so lock this object:
+ fIsImmutable = true;
+ }
+
+ /**
+ * If is chosen, or built-in derived types by restriction
+ */
+ void applyFacets(XSFacets facets, short presentFacet, short fixedFacet, short patternType, ValidationContext context)
+ throws InvalidDatatypeFacetException {
+
+ // if the object is immutable, should not apply facets...
+ if(fIsImmutable) return;
+ ValidatedInfo tempInfo = new ValidatedInfo();
+
+ // clear facets. because we always inherit facets in the constructor
+ // REVISIT: in fact, we don't need to clear them.
+ // we can convert 5 string values (4 bounds + 1 enum) to actual values,
+ // store them somewhere, then do facet checking at once, instead of
+ // going through the following steps. (lots of checking are redundant:
+ // for example, ((presentFacet & FACET_XXX) != 0))
+
+ fFacetsDefined = 0;
+ fFixedFacet = 0;
+
+ int result = 0 ;
+
+ // step 1: parse present facets
+ short allowedFacet = fDVs[fValidationDV].getAllowedFacets();
+
+ // length
+ if ((presentFacet & FACET_LENGTH) != 0) {
+ if ((allowedFacet & FACET_LENGTH) == 0) {
+ reportError("cos-applicable-facets", new Object[]{"length", fTypeName});
+ } else {
+ fLength = facets.length;
+ lengthAnnotation = facets.lengthAnnotation;
+ fFacetsDefined |= FACET_LENGTH;
+ if ((fixedFacet & FACET_LENGTH) != 0)
+ fFixedFacet |= FACET_LENGTH;
+ }
+ }
+ // minLength
+ if ((presentFacet & FACET_MINLENGTH) != 0) {
+ if ((allowedFacet & FACET_MINLENGTH) == 0) {
+ reportError("cos-applicable-facets", new Object[]{"minLength", fTypeName});
+ } else {
+ fMinLength = facets.minLength;
+ minLengthAnnotation = facets.minLengthAnnotation;
+ fFacetsDefined |= FACET_MINLENGTH;
+ if ((fixedFacet & FACET_MINLENGTH) != 0)
+ fFixedFacet |= FACET_MINLENGTH;
+ }
+ }
+ // maxLength
+ if ((presentFacet & FACET_MAXLENGTH) != 0) {
+ if ((allowedFacet & FACET_MAXLENGTH) == 0) {
+ reportError("cos-applicable-facets", new Object[]{"maxLength", fTypeName});
+ } else {
+ fMaxLength = facets.maxLength;
+ maxLengthAnnotation = facets.maxLengthAnnotation;
+ fFacetsDefined |= FACET_MAXLENGTH;
+ if ((fixedFacet & FACET_MAXLENGTH) != 0)
+ fFixedFacet |= FACET_MAXLENGTH;
+ }
+ }
+ // pattern
+ if ((presentFacet & FACET_PATTERN) != 0) {
+ if ((allowedFacet & FACET_PATTERN) == 0) {
+ reportError("cos-applicable-facets", new Object[]{"pattern", fTypeName});
+ } else {
+ patternAnnotations = facets.patternAnnotations;
+ RegularExpression regex = null;
+ try {
+ regex = new RegularExpression(facets.pattern, "X", context.getLocale());
+ } catch (Exception e) {
+ reportError("InvalidRegex", new Object[]{facets.pattern, e.getLocalizedMessage()});
+ }
+ if (regex != null) {
+ fPattern = new Vector();
+ fPattern.addElement(regex);
+ fPatternStr = new Vector();
+ fPatternStr.addElement(facets.pattern);
+ fFacetsDefined |= FACET_PATTERN;
+ if ((fixedFacet & FACET_PATTERN) != 0)
+ fFixedFacet |= FACET_PATTERN;
+ }
+ }
+ }
+
+ // whiteSpace
+ if ((presentFacet & FACET_WHITESPACE) != 0) {
+ if ((allowedFacet & FACET_WHITESPACE) == 0) {
+ reportError("cos-applicable-facets", new Object[]{"whiteSpace", fTypeName});
+ } else {
+ fWhiteSpace = facets.whiteSpace;
+ whiteSpaceAnnotation = facets.whiteSpaceAnnotation;
+ fFacetsDefined |= FACET_WHITESPACE;
+ if ((fixedFacet & FACET_WHITESPACE) != 0)
+ fFixedFacet |= FACET_WHITESPACE;
+ }
+ }
+ // enumeration
+ if ((presentFacet & FACET_ENUMERATION) != 0) {
+ if ((allowedFacet & FACET_ENUMERATION) == 0) {
+ reportError("cos-applicable-facets", new Object[]{"enumeration", fTypeName});
+ } else {
+ Vector enumVals = facets.enumeration;
+ int size = enumVals.size();
+ fEnumeration = new ValidatedInfo[size];
+ Vector enumNSDecls = facets.enumNSDecls;
+ ValidationContextImpl ctx = new ValidationContextImpl(context);
+ enumerationAnnotations = facets.enumAnnotations;
+ fEnumerationSize = 0;
+ for (int i = 0; i < size; i++) {
+ if (enumNSDecls != null)
+ ctx.setNSContext((NamespaceContext)enumNSDecls.elementAt(i));
+ try {
+ ValidatedInfo info = getActualEnumValue((String)enumVals.elementAt(i), ctx, null);
+ // check 4.3.5.c0 must: enumeration values from the value space of base
+ fEnumeration[fEnumerationSize++] = info;
+ } catch (InvalidDatatypeValueException ide) {
+ reportError("enumeration-valid-restriction", new Object[]{enumVals.elementAt(i), this.getBaseType().getName()});
+ }
+ }
+ fFacetsDefined |= FACET_ENUMERATION;
+ if ((fixedFacet & FACET_ENUMERATION) != 0)
+ fFixedFacet |= FACET_ENUMERATION;
+ }
+ }
+
+ // maxInclusive
+ if ((presentFacet & FACET_MAXINCLUSIVE) != 0) {
+ if ((allowedFacet & FACET_MAXINCLUSIVE) == 0) {
+ reportError("cos-applicable-facets", new Object[]{"maxInclusive", fTypeName});
+ } else {
+ maxInclusiveAnnotation = facets.maxInclusiveAnnotation;
+ try {
+ fMaxInclusive = fBase.getActualValue(facets.maxInclusive, context, tempInfo, true);
+ fFacetsDefined |= FACET_MAXINCLUSIVE;
+ if ((fixedFacet & FACET_MAXINCLUSIVE) != 0)
+ fFixedFacet |= FACET_MAXINCLUSIVE;
+ } catch (InvalidDatatypeValueException ide) {
+ reportError(ide.getKey(), ide.getArgs());
+ reportError("FacetValueFromBase", new Object[]{fTypeName, facets.maxInclusive,
+ "maxInclusive", fBase.getName()});
+ }
+
+ // check against fixed value in base
+ if (((fBase.fFacetsDefined & FACET_MAXINCLUSIVE) != 0)) {
+ if ((fBase.fFixedFacet & FACET_MAXINCLUSIVE) != 0) {
+ if (fDVs[fValidationDV].compare(fMaxInclusive, fBase.fMaxInclusive) != 0)
+ reportError( "FixedFacetValue", new Object[]{"maxInclusive", fMaxInclusive, fBase.fMaxInclusive, fTypeName});
+ }
+ }
+ // maxInclusive from base
+ try {
+ fBase.validate(context, tempInfo);
+ } catch (InvalidDatatypeValueException ide) {
+ reportError(ide.getKey(), ide.getArgs());
+ reportError("FacetValueFromBase", new Object[]{fTypeName, facets.maxInclusive,
+ "maxInclusive", fBase.getName()});
+ }
+ }
+ }
+
+ // maxExclusive
+ boolean needCheckBase = true;
+ if ((presentFacet & FACET_MAXEXCLUSIVE) != 0) {
+ if ((allowedFacet & FACET_MAXEXCLUSIVE) == 0) {
+ reportError("cos-applicable-facets", new Object[]{"maxExclusive", fTypeName});
+ } else {
+ maxExclusiveAnnotation = facets.maxExclusiveAnnotation;
+ try {
+ fMaxExclusive = fBase.getActualValue(facets.maxExclusive, context, tempInfo, true);
+ fFacetsDefined |= FACET_MAXEXCLUSIVE;
+ if ((fixedFacet & FACET_MAXEXCLUSIVE) != 0)
+ fFixedFacet |= FACET_MAXEXCLUSIVE;
+ } catch (InvalidDatatypeValueException ide) {
+ reportError(ide.getKey(), ide.getArgs());
+ reportError("FacetValueFromBase", new Object[]{fTypeName, facets.maxExclusive,
+ "maxExclusive", fBase.getName()});
+ }
+
+ // check against fixed value in base
+ if (((fBase.fFacetsDefined & FACET_MAXEXCLUSIVE) != 0)) {
+ result = fDVs[fValidationDV].compare(fMaxExclusive, fBase.fMaxExclusive);
+ if ((fBase.fFixedFacet & FACET_MAXEXCLUSIVE) != 0 && result != 0) {
+ reportError( "FixedFacetValue", new Object[]{"maxExclusive", facets.maxExclusive, fBase.fMaxExclusive, fTypeName});
+ }
+ if (result == 0) {
+ needCheckBase = false;
+ }
+ }
+ // maxExclusive from base
+ if (needCheckBase) {
+ try {
+ fBase.validate(context, tempInfo);
+ } catch (InvalidDatatypeValueException ide) {
+ reportError(ide.getKey(), ide.getArgs());
+ reportError("FacetValueFromBase", new Object[]{fTypeName, facets.maxExclusive,
+ "maxExclusive", fBase.getName()});
+ }
+ }
+ // If maxExclusive == base.maxExclusive, then we only need to check
+ // maxExclusive <= base.maxInclusive
+ else if (((fBase.fFacetsDefined & FACET_MAXINCLUSIVE) != 0)) {
+ if (fDVs[fValidationDV].compare(fMaxExclusive, fBase.fMaxInclusive) > 0) {
+ reportError( "maxExclusive-valid-restriction.2", new Object[]{facets.maxExclusive, fBase.fMaxInclusive});
+ }
+ }
+ }
+ }
+ // minExclusive
+ needCheckBase = true;
+ if ((presentFacet & FACET_MINEXCLUSIVE) != 0) {
+ if ((allowedFacet & FACET_MINEXCLUSIVE) == 0) {
+ reportError("cos-applicable-facets", new Object[]{"minExclusive", fTypeName});
+ } else {
+ minExclusiveAnnotation = facets.minExclusiveAnnotation;
+ try {
+ fMinExclusive = fBase.getActualValue(facets.minExclusive, context, tempInfo, true);
+ fFacetsDefined |= FACET_MINEXCLUSIVE;
+ if ((fixedFacet & FACET_MINEXCLUSIVE) != 0)
+ fFixedFacet |= FACET_MINEXCLUSIVE;
+ } catch (InvalidDatatypeValueException ide) {
+ reportError(ide.getKey(), ide.getArgs());
+ reportError("FacetValueFromBase", new Object[]{fTypeName, facets.minExclusive,
+ "minExclusive", fBase.getName()});
+ }
+
+ // check against fixed value in base
+ if (((fBase.fFacetsDefined & FACET_MINEXCLUSIVE) != 0)) {
+ result = fDVs[fValidationDV].compare(fMinExclusive, fBase.fMinExclusive);
+ if ((fBase.fFixedFacet & FACET_MINEXCLUSIVE) != 0 && result != 0) {
+ reportError( "FixedFacetValue", new Object[]{"minExclusive", facets.minExclusive, fBase.fMinExclusive, fTypeName});
+ }
+ if (result == 0) {
+ needCheckBase = false;
+ }
+ }
+ // minExclusive from base
+ if (needCheckBase) {
+ try {
+ fBase.validate(context, tempInfo);
+ } catch (InvalidDatatypeValueException ide) {
+ reportError(ide.getKey(), ide.getArgs());
+ reportError("FacetValueFromBase", new Object[]{fTypeName, facets.minExclusive,
+ "minExclusive", fBase.getName()});
+ }
+ }
+ // If minExclusive == base.minExclusive, then we only need to check
+ // minExclusive >= base.minInclusive
+ else if (((fBase.fFacetsDefined & FACET_MININCLUSIVE) != 0)) {
+ if (fDVs[fValidationDV].compare(fMinExclusive, fBase.fMinInclusive) < 0) {
+ reportError( "minExclusive-valid-restriction.3", new Object[]{facets.minExclusive, fBase.fMinInclusive});
+ }
+ }
+ }
+ }
+ // minInclusive
+ if ((presentFacet & FACET_MININCLUSIVE) != 0) {
+ if ((allowedFacet & FACET_MININCLUSIVE) == 0) {
+ reportError("cos-applicable-facets", new Object[]{"minInclusive", fTypeName});
+ } else {
+ minInclusiveAnnotation = facets.minInclusiveAnnotation;
+ try {
+ fMinInclusive = fBase.getActualValue(facets.minInclusive, context, tempInfo, true);
+ fFacetsDefined |= FACET_MININCLUSIVE;
+ if ((fixedFacet & FACET_MININCLUSIVE) != 0)
+ fFixedFacet |= FACET_MININCLUSIVE;
+ } catch (InvalidDatatypeValueException ide) {
+ reportError(ide.getKey(), ide.getArgs());
+ reportError("FacetValueFromBase", new Object[]{fTypeName, facets.minInclusive,
+ "minInclusive", fBase.getName()});
+ }
+
+ // check against fixed value in base
+ if (((fBase.fFacetsDefined & FACET_MININCLUSIVE) != 0)) {
+ if ((fBase.fFixedFacet & FACET_MININCLUSIVE) != 0) {
+ if (fDVs[fValidationDV].compare(fMinInclusive, fBase.fMinInclusive) != 0)
+ reportError( "FixedFacetValue", new Object[]{"minInclusive", facets.minInclusive, fBase.fMinInclusive, fTypeName});
+ }
+ }
+ // minInclusive from base
+ try {
+ fBase.validate(context, tempInfo);
+ } catch (InvalidDatatypeValueException ide) {
+ reportError(ide.getKey(), ide.getArgs());
+ reportError("FacetValueFromBase", new Object[]{fTypeName, facets.minInclusive,
+ "minInclusive", fBase.getName()});
+ }
+ }
+ }
+
+ // totalDigits
+ if ((presentFacet & FACET_TOTALDIGITS) != 0) {
+ if ((allowedFacet & FACET_TOTALDIGITS) == 0) {
+ reportError("cos-applicable-facets", new Object[]{"totalDigits", fTypeName});
+ } else {
+ totalDigitsAnnotation = facets.totalDigitsAnnotation;
+ fTotalDigits = facets.totalDigits;
+ fFacetsDefined |= FACET_TOTALDIGITS;
+ if ((fixedFacet & FACET_TOTALDIGITS) != 0)
+ fFixedFacet |= FACET_TOTALDIGITS;
+ }
+ }
+ // fractionDigits
+ if ((presentFacet & FACET_FRACTIONDIGITS) != 0) {
+ if ((allowedFacet & FACET_FRACTIONDIGITS) == 0) {
+ reportError("cos-applicable-facets", new Object[]{"fractionDigits", fTypeName});
+ } else {
+ fFractionDigits = facets.fractionDigits;
+ fractionDigitsAnnotation = facets.fractionDigitsAnnotation;
+ fFacetsDefined |= FACET_FRACTIONDIGITS;
+ if ((fixedFacet & FACET_FRACTIONDIGITS) != 0)
+ fFixedFacet |= FACET_FRACTIONDIGITS;
+ }
+ }
+
+ // token type: internal use, so do less checking
+ if (patternType != SPECIAL_PATTERN_NONE) {
+ fPatternType = patternType;
+ }
+
+ // step 2: check facets against each other: length, bounds
+ if(fFacetsDefined != 0) {
+
+ // check 4.3.2.c1 must: minLength <= maxLength
+ if(((fFacetsDefined & FACET_MINLENGTH ) != 0 ) && ((fFacetsDefined & FACET_MAXLENGTH) != 0))
+ {
+ if(fMinLength > fMaxLength)
+ reportError("minLength-less-than-equal-to-maxLength", new Object[]{Integer.toString(fMinLength), Integer.toString(fMaxLength), fTypeName});
+ }
+
+ // check 4.3.8.c1 error: maxInclusive + maxExclusive
+ if (((fFacetsDefined & FACET_MAXEXCLUSIVE) != 0) && ((fFacetsDefined & FACET_MAXINCLUSIVE) != 0)) {
+ reportError( "maxInclusive-maxExclusive", new Object[]{fMaxInclusive, fMaxExclusive, fTypeName});
+ }
+
+ // check 4.3.9.c1 error: minInclusive + minExclusive
+ if (((fFacetsDefined & FACET_MINEXCLUSIVE) != 0) && ((fFacetsDefined & FACET_MININCLUSIVE) != 0)) {
+ reportError("minInclusive-minExclusive", new Object[]{fMinInclusive, fMinExclusive, fTypeName});
+ }
+
+ // check 4.3.7.c1 must: minInclusive <= maxInclusive
+ if (((fFacetsDefined & FACET_MAXINCLUSIVE) != 0) && ((fFacetsDefined & FACET_MININCLUSIVE) != 0)) {
+ result = fDVs[fValidationDV].compare(fMinInclusive, fMaxInclusive);
+ if (result != -1 && result != 0)
+ reportError("minInclusive-less-than-equal-to-maxInclusive", new Object[]{fMinInclusive, fMaxInclusive, fTypeName});
+ }
+
+ // check 4.3.8.c2 must: minExclusive <= maxExclusive ??? minExclusive < maxExclusive
+ if (((fFacetsDefined & FACET_MAXEXCLUSIVE) != 0) && ((fFacetsDefined & FACET_MINEXCLUSIVE) != 0)) {
+ result = fDVs[fValidationDV].compare(fMinExclusive, fMaxExclusive);
+ if (result != -1 && result != 0)
+ reportError( "minExclusive-less-than-equal-to-maxExclusive", new Object[]{fMinExclusive, fMaxExclusive, fTypeName});
+ }
+
+ // check 4.3.9.c2 must: minExclusive < maxInclusive
+ if (((fFacetsDefined & FACET_MAXINCLUSIVE) != 0) && ((fFacetsDefined & FACET_MINEXCLUSIVE) != 0)) {
+ if (fDVs[fValidationDV].compare(fMinExclusive, fMaxInclusive) != -1)
+ reportError( "minExclusive-less-than-maxInclusive", new Object[]{fMinExclusive, fMaxInclusive, fTypeName});
+ }
+
+ // check 4.3.10.c1 must: minInclusive < maxExclusive
+ if (((fFacetsDefined & FACET_MAXEXCLUSIVE) != 0) && ((fFacetsDefined & FACET_MININCLUSIVE) != 0)) {
+ if (fDVs[fValidationDV].compare(fMinInclusive, fMaxExclusive) != -1)
+ reportError( "minInclusive-less-than-maxExclusive", new Object[]{fMinInclusive, fMaxExclusive, fTypeName});
+ }
+
+ // check 4.3.12.c1 must: fractionDigits <= totalDigits
+ if (((fFacetsDefined & FACET_FRACTIONDIGITS) != 0) &&
+ ((fFacetsDefined & FACET_TOTALDIGITS) != 0)) {
+ if (fFractionDigits > fTotalDigits)
+ reportError( "fractionDigits-totalDigits", new Object[]{Integer.toString(fFractionDigits), Integer.toString(fTotalDigits), fTypeName});
+ }
+
+ // step 3: check facets against base
+ // check 4.3.1.c1 error: length & (fBase.maxLength | fBase.minLength)
+ if((fFacetsDefined & FACET_LENGTH) != 0 ){
+ if ((fBase.fFacetsDefined & FACET_MINLENGTH) != 0 &&
+ fLength < fBase.fMinLength) {
+ // length, fBase.minLength and fBase.maxLength defined
+ reportError("length-minLength-maxLength.1.1", new Object[]{fTypeName, Integer.toString(fLength), Integer.toString(fBase.fMinLength)});
+ }
+ if ((fBase.fFacetsDefined & FACET_MAXLENGTH) != 0 &&
+ fLength > fBase.fMaxLength) {
+ // length and fBase.maxLength defined
+ reportError("length-minLength-maxLength.2.1", new Object[]{fTypeName, Integer.toString(fLength), Integer.toString(fBase.fMaxLength)});
+ }
+ if ( (fBase.fFacetsDefined & FACET_LENGTH) != 0 ) {
+ // check 4.3.1.c2 error: length != fBase.length
+ if ( fLength != fBase.fLength )
+ reportError( "length-valid-restriction", new Object[]{Integer.toString(fLength), Integer.toString(fBase.fLength), fTypeName});
+ }
+ }
+
+ // check 4.3.1.c1 error: fBase.length & (maxLength | minLength)
+ if((fBase.fFacetsDefined & FACET_LENGTH) != 0 || (fFacetsDefined & FACET_LENGTH) != 0){
+ if ((fFacetsDefined & FACET_MINLENGTH) != 0){
+ if (fBase.fLength < fMinLength) {
+ // fBase.length, minLength and maxLength defined
+ reportError("length-minLength-maxLength.1.1", new Object[]{fTypeName, Integer.toString(fBase.fLength), Integer.toString(fMinLength)});
+ }
+ if ((fBase.fFacetsDefined & FACET_MINLENGTH) == 0){
+ reportError("length-minLength-maxLength.1.2.a", new Object[]{fTypeName});
+ }
+ if (fMinLength != fBase.fMinLength){
+ reportError("length-minLength-maxLength.1.2.b", new Object[]{fTypeName, Integer.toString(fMinLength), Integer.toString(fBase.fMinLength)});
+ }
+ }
+ if ((fFacetsDefined & FACET_MAXLENGTH) != 0){
+ if (fBase.fLength > fMaxLength) {
+ // fBase.length, minLength and maxLength defined
+ reportError("length-minLength-maxLength.2.1", new Object[]{fTypeName, Integer.toString(fBase.fLength), Integer.toString(fMaxLength)});
+ }
+ if ((fBase.fFacetsDefined & FACET_MAXLENGTH) == 0){
+ reportError("length-minLength-maxLength.2.2.a", new Object[]{fTypeName});
+ }
+ if (fMaxLength != fBase.fMaxLength){
+ reportError("length-minLength-maxLength.2.2.b", new Object[]{fTypeName, Integer.toString(fMaxLength), Integer.toString(fBase.fBase.fMaxLength)});
+ }
+ }
+ }
+
+ // check 4.3.2.c1 must: minLength <= fBase.maxLength
+ if ( ((fFacetsDefined & FACET_MINLENGTH ) != 0 ) ) {
+ if ( (fBase.fFacetsDefined & FACET_MAXLENGTH ) != 0 ) {
+ if ( fMinLength > fBase.fMaxLength ) {
+ reportError("minLength-less-than-equal-to-maxLength", new Object[]{Integer.toString(fMinLength), Integer.toString(fBase.fMaxLength), fTypeName});
+ }
+ }
+ else if ( (fBase.fFacetsDefined & FACET_MINLENGTH) != 0 ) {
+ if ( (fBase.fFixedFacet & FACET_MINLENGTH) != 0 && fMinLength != fBase.fMinLength ) {
+ reportError( "FixedFacetValue", new Object[]{"minLength", Integer.toString(fMinLength), Integer.toString(fBase.fMinLength), fTypeName});
+ }
+
+ // check 4.3.2.c2 error: minLength < fBase.minLength
+ if ( fMinLength < fBase.fMinLength ) {
+ reportError( "minLength-valid-restriction", new Object[]{Integer.toString(fMinLength), Integer.toString(fBase.fMinLength), fTypeName});
+ }
+ }
+ }
+
+
+ // check 4.3.2.c1 must: maxLength < fBase.minLength
+ if ( ((fFacetsDefined & FACET_MAXLENGTH ) != 0 ) && ((fBase.fFacetsDefined & FACET_MINLENGTH ) != 0 )) {
+ if ( fMaxLength < fBase.fMinLength) {
+ reportError("minLength-less-than-equal-to-maxLength", new Object[]{Integer.toString(fBase.fMinLength), Integer.toString(fMaxLength)});
+ }
+ }
+
+ // check 4.3.3.c1 error: maxLength > fBase.maxLength
+ if ( (fFacetsDefined & FACET_MAXLENGTH) != 0 ) {
+ if ( (fBase.fFacetsDefined & FACET_MAXLENGTH) != 0 ){
+ if(( (fBase.fFixedFacet & FACET_MAXLENGTH) != 0 )&& fMaxLength != fBase.fMaxLength ) {
+ reportError( "FixedFacetValue", new Object[]{"maxLength", Integer.toString(fMaxLength), Integer.toString(fBase.fMaxLength), fTypeName});
+ }
+ if ( fMaxLength > fBase.fMaxLength ) {
+ reportError( "maxLength-valid-restriction", new Object[]{Integer.toString(fMaxLength), Integer.toString(fBase.fMaxLength), fTypeName});
+ }
+ }
+ }
+
+ /* // check 4.3.7.c2 error:
+ // maxInclusive > fBase.maxInclusive
+ // maxInclusive >= fBase.maxExclusive
+ // maxInclusive < fBase.minInclusive
+ // maxInclusive <= fBase.minExclusive
+
+ if (((fFacetsDefined & FACET_MAXINCLUSIVE) != 0)) {
+ if (((fBase.fFacetsDefined & FACET_MAXINCLUSIVE) != 0)) {
+ result = fDVs[fValidationDV].compare(fMaxInclusive, fBase.fMaxInclusive);
+ if ((fBase.fFixedFacet & FACET_MAXINCLUSIVE) != 0 && result != 0) {
+ reportError( "FixedFacetValue", new Object[]{"maxInclusive", fMaxInclusive, fBase.fMaxInclusive, fTypeName});
+ }
+ if (result != -1 && result != 0) {
+ reportError( "maxInclusive-valid-restriction.1", new Object[]{fMaxInclusive, fBase.fMaxInclusive, fTypeName});
+ }
+ }
+ if (((fBase.fFacetsDefined & FACET_MAXEXCLUSIVE) != 0) &&
+ fDVs[fValidationDV].compare(fMaxInclusive, fBase.fMaxExclusive) != -1){
+ reportError( "maxInclusive-valid-restriction.1", new Object[]{fMaxInclusive, fBase.fMaxExclusive, fTypeName});
+ }
+
+ if ((( fBase.fFacetsDefined & FACET_MININCLUSIVE) != 0)) {
+ result = fDVs[fValidationDV].compare(fMaxInclusive, fBase.fMinInclusive);
+ if (result != 1 && result != 0) {
+ reportError( "maxInclusive-valid-restriction.1", new Object[]{fMaxInclusive, fBase.fMinInclusive, fTypeName});
+ }
+ }
+
+ if ((( fBase.fFacetsDefined & FACET_MINEXCLUSIVE) != 0) &&
+ fDVs[fValidationDV].compare(fMaxInclusive, fBase.fMinExclusive ) != 1)
+ reportError( "maxInclusive-valid-restriction.1", new Object[]{fMaxInclusive, fBase.fMinExclusive, fTypeName});
+ }
+
+ // check 4.3.8.c3 error:
+ // maxExclusive > fBase.maxExclusive
+ // maxExclusive > fBase.maxInclusive
+ // maxExclusive <= fBase.minInclusive
+ // maxExclusive <= fBase.minExclusive
+ if (((fFacetsDefined & FACET_MAXEXCLUSIVE) != 0)) {
+ if ((( fBase.fFacetsDefined & FACET_MAXEXCLUSIVE) != 0)) {
+ result= fDVs[fValidationDV].compare(fMaxExclusive, fBase.fMaxExclusive);
+ if ((fBase.fFixedFacet & FACET_MAXEXCLUSIVE) != 0 && result != 0) {
+ reportError( "FixedFacetValue", new Object[]{"maxExclusive", fMaxExclusive, fBase.fMaxExclusive, fTypeName});
+ }
+ if (result != -1 && result != 0) {
+ reportError( "maxExclusive-valid-restriction.1", new Object[]{fMaxExclusive, fBase.fMaxExclusive, fTypeName});
+ }
+ }
+
+ if ((( fBase.fFacetsDefined & FACET_MAXINCLUSIVE) != 0)) {
+ result= fDVs[fValidationDV].compare(fMaxExclusive, fBase.fMaxInclusive);
+ if (result != -1 && result != 0) {
+ reportError( "maxExclusive-valid-restriction.2", new Object[]{fMaxExclusive, fBase.fMaxInclusive, fTypeName});
+ }
+ }
+
+ if ((( fBase.fFacetsDefined & FACET_MINEXCLUSIVE) != 0) &&
+ fDVs[fValidationDV].compare(fMaxExclusive, fBase.fMinExclusive ) != 1)
+ reportError( "maxExclusive-valid-restriction.3", new Object[]{fMaxExclusive, fBase.fMinExclusive, fTypeName});
+
+ if ((( fBase.fFacetsDefined & FACET_MININCLUSIVE) != 0) &&
+ fDVs[fValidationDV].compare(fMaxExclusive, fBase.fMinInclusive) != 1)
+ reportError( "maxExclusive-valid-restriction.4", new Object[]{fMaxExclusive, fBase.fMinInclusive, fTypeName});
+ }
+
+ // check 4.3.9.c3 error:
+ // minExclusive < fBase.minExclusive
+ // minExclusive > fBase.maxInclusive
+ // minExclusive < fBase.minInclusive
+ // minExclusive >= fBase.maxExclusive
+ if (((fFacetsDefined & FACET_MINEXCLUSIVE) != 0)) {
+ if ((( fBase.fFacetsDefined & FACET_MINEXCLUSIVE) != 0)) {
+ result= fDVs[fValidationDV].compare(fMinExclusive, fBase.fMinExclusive);
+ if ((fBase.fFixedFacet & FACET_MINEXCLUSIVE) != 0 && result != 0) {
+ reportError( "FixedFacetValue", new Object[]{"minExclusive", fMinExclusive, fBase.fMinExclusive, fTypeName});
+ }
+ if (result != 1 && result != 0) {
+ reportError( "minExclusive-valid-restriction.1", new Object[]{fMinExclusive, fBase.fMinExclusive, fTypeName});
+ }
+ }
+
+ if ((( fBase.fFacetsDefined & FACET_MAXINCLUSIVE) != 0)) {
+ result=fDVs[fValidationDV].compare(fMinExclusive, fBase.fMaxInclusive);
+
+ if (result != -1 && result != 0) {
+ reportError( "minExclusive-valid-restriction.2", new Object[]{fMinExclusive, fBase.fMaxInclusive, fTypeName});
+ }
+ }
+
+ if ((( fBase.fFacetsDefined & FACET_MININCLUSIVE) != 0)) {
+ result = fDVs[fValidationDV].compare(fMinExclusive, fBase.fMinInclusive);
+
+ if (result != 1 && result != 0) {
+ reportError( "minExclusive-valid-restriction.3", new Object[]{fMinExclusive, fBase.fMinInclusive, fTypeName});
+ }
+ }
+
+ if ((( fBase.fFacetsDefined & FACET_MAXEXCLUSIVE) != 0) &&
+ fDVs[fValidationDV].compare(fMinExclusive, fBase.fMaxExclusive) != -1)
+ reportError( "minExclusive-valid-restriction.4", new Object[]{fMinExclusive, fBase.fMaxExclusive, fTypeName});
+ }
+
+ // check 4.3.10.c2 error:
+ // minInclusive < fBase.minInclusive
+ // minInclusive > fBase.maxInclusive
+ // minInclusive <= fBase.minExclusive
+ // minInclusive >= fBase.maxExclusive
+ if (((fFacetsDefined & FACET_MININCLUSIVE) != 0)) {
+ if (((fBase.fFacetsDefined & FACET_MININCLUSIVE) != 0)) {
+ result = fDVs[fValidationDV].compare(fMinInclusive, fBase.fMinInclusive);
+
+ if ((fBase.fFixedFacet & FACET_MININCLUSIVE) != 0 && result != 0) {
+ reportError( "FixedFacetValue", new Object[]{"minInclusive", fMinInclusive, fBase.fMinInclusive, fTypeName});
+ }
+ if (result != 1 && result != 0) {
+ reportError( "minInclusive-valid-restriction.1", new Object[]{fMinInclusive, fBase.fMinInclusive, fTypeName});
+ }
+ }
+ if ((( fBase.fFacetsDefined & FACET_MAXINCLUSIVE) != 0)) {
+ result=fDVs[fValidationDV].compare(fMinInclusive, fBase.fMaxInclusive);
+ if (result != -1 && result != 0) {
+ reportError( "minInclusive-valid-restriction.2", new Object[]{fMinInclusive, fBase.fMaxInclusive, fTypeName});
+ }
+ }
+ if ((( fBase.fFacetsDefined & FACET_MINEXCLUSIVE) != 0) &&
+ fDVs[fValidationDV].compare(fMinInclusive, fBase.fMinExclusive ) != 1)
+ reportError( "minInclusive-valid-restriction.3", new Object[]{fMinInclusive, fBase.fMinExclusive, fTypeName});
+ if ((( fBase.fFacetsDefined & FACET_MAXEXCLUSIVE) != 0) &&
+ fDVs[fValidationDV].compare(fMinInclusive, fBase.fMaxExclusive) != -1)
+ reportError( "minInclusive-valid-restriction.4", new Object[]{fMinInclusive, fBase.fMaxExclusive, fTypeName});
+ }
+ */
+ // check 4.3.11.c1 error: totalDigits > fBase.totalDigits
+ if (((fFacetsDefined & FACET_TOTALDIGITS) != 0)) {
+ if ((( fBase.fFacetsDefined & FACET_TOTALDIGITS) != 0)) {
+ if ((fBase.fFixedFacet & FACET_TOTALDIGITS) != 0 && fTotalDigits != fBase.fTotalDigits) {
+ reportError("FixedFacetValue", new Object[]{"totalDigits", Integer.toString(fTotalDigits), Integer.toString(fBase.fTotalDigits), fTypeName});
+ }
+ if (fTotalDigits > fBase.fTotalDigits) {
+ reportError( "totalDigits-valid-restriction", new Object[]{Integer.toString(fTotalDigits), Integer.toString(fBase.fTotalDigits), fTypeName});
+ }
+ }
+ }
+
+ // check 4.3.12.c1 must: fractionDigits <= base.totalDigits
+ if ((fFacetsDefined & FACET_FRACTIONDIGITS) != 0) {
+ if ((fBase.fFacetsDefined & FACET_TOTALDIGITS) != 0) {
+ if (fFractionDigits > fBase.fTotalDigits)
+ reportError( "fractionDigits-totalDigits", new Object[]{Integer.toString(fFractionDigits), Integer.toString(fTotalDigits), fTypeName});
+ }
+ }
+
+ // check 4.3.12.c2 error: fractionDigits > fBase.fractionDigits
+ // check fixed value for fractionDigits
+ if (((fFacetsDefined & FACET_FRACTIONDIGITS) != 0)) {
+ if ((( fBase.fFacetsDefined & FACET_FRACTIONDIGITS) != 0)) {
+ if (((fBase.fFixedFacet & FACET_FRACTIONDIGITS) != 0 && fFractionDigits != fBase.fFractionDigits) ||
+ (fValidationDV == DV_INTEGER && fFractionDigits != 0)) {
+ reportError("FixedFacetValue", new Object[]{"fractionDigits", Integer.toString(fFractionDigits), Integer.toString(fBase.fFractionDigits), fTypeName});
+ }
+ if (fFractionDigits > fBase.fFractionDigits) {
+ reportError( "fractionDigits-valid-restriction", new Object[]{Integer.toString(fFractionDigits), Integer.toString(fBase.fFractionDigits), fTypeName});
+ }
+ }
+ else if (fValidationDV == DV_INTEGER && fFractionDigits != 0) {
+ reportError("FixedFacetValue", new Object[]{"fractionDigits", Integer.toString(fFractionDigits), "0", fTypeName});
+ }
+ }
+
+ // check 4.3.6.c1 error:
+ // (whiteSpace = preserve || whiteSpace = replace) && fBase.whiteSpace = collapese or
+ // whiteSpace = preserve && fBase.whiteSpace = replace
+
+ if ( (fFacetsDefined & FACET_WHITESPACE) != 0 && (fBase.fFacetsDefined & FACET_WHITESPACE) != 0 ){
+ if ( (fBase.fFixedFacet & FACET_WHITESPACE) != 0 && fWhiteSpace != fBase.fWhiteSpace ) {
+ reportError( "FixedFacetValue", new Object[]{"whiteSpace", whiteSpaceValue(fWhiteSpace), whiteSpaceValue(fBase.fWhiteSpace), fTypeName});
+ }
+
+ if ( fWhiteSpace == WS_PRESERVE && fBase.fWhiteSpace == WS_COLLAPSE ){
+ reportError( "whiteSpace-valid-restriction.1", new Object[]{fTypeName, "preserve"});
+ }
+ if ( fWhiteSpace == WS_REPLACE && fBase.fWhiteSpace == WS_COLLAPSE ){
+ reportError( "whiteSpace-valid-restriction.1", new Object[]{fTypeName, "replace"});
+ }
+ if ( fWhiteSpace == WS_PRESERVE && fBase.fWhiteSpace == WS_REPLACE ){
+ reportError( "whiteSpace-valid-restriction.2", new Object[]{fTypeName});
+ }
+ }
+ }//fFacetsDefined != null
+
+ // step 4: inherit other facets from base (including fTokeyType)
+
+ // inherit length
+ if ( (fFacetsDefined & FACET_LENGTH) == 0 && (fBase.fFacetsDefined & FACET_LENGTH) != 0 ) {
+ fFacetsDefined |= FACET_LENGTH;
+ fLength = fBase.fLength;
+ lengthAnnotation = fBase.lengthAnnotation;
+ }
+ // inherit minLength
+ if ( (fFacetsDefined & FACET_MINLENGTH) == 0 && (fBase.fFacetsDefined & FACET_MINLENGTH) != 0 ) {
+ fFacetsDefined |= FACET_MINLENGTH;
+ fMinLength = fBase.fMinLength;
+ minLengthAnnotation = fBase.minLengthAnnotation;
+ }
+ // inherit maxLength
+ if ((fFacetsDefined & FACET_MAXLENGTH) == 0 && (fBase.fFacetsDefined & FACET_MAXLENGTH) != 0 ) {
+ fFacetsDefined |= FACET_MAXLENGTH;
+ fMaxLength = fBase.fMaxLength;
+ maxLengthAnnotation = fBase.maxLengthAnnotation;
+ }
+ // inherit pattern
+ if ( (fBase.fFacetsDefined & FACET_PATTERN) != 0 ) {
+ if ((fFacetsDefined & FACET_PATTERN) == 0) {
+ fFacetsDefined |= FACET_PATTERN;
+ fPattern = fBase.fPattern;
+ fPatternStr = fBase.fPatternStr;
+ patternAnnotations = fBase.patternAnnotations;
+ }
+ else {
+ for (int i = fBase.fPattern.size()-1; i >= 0; --i) {
+ fPattern.addElement(fBase.fPattern.elementAt(i));
+ fPatternStr.addElement(fBase.fPatternStr.elementAt(i));
+ }
+ if (fBase.patternAnnotations != null) {
+ if (patternAnnotations != null) {
+ for (int i = fBase.patternAnnotations.getLength()-1; i >= 0; --i) {
+ patternAnnotations.addXSObject(fBase.patternAnnotations.item(i));
+ }
+ }
+ else {
+ patternAnnotations = fBase.patternAnnotations;
+ }
+ }
+ }
+ }
+ // inherit whiteSpace
+ if ( (fFacetsDefined & FACET_WHITESPACE) == 0 && (fBase.fFacetsDefined & FACET_WHITESPACE) != 0 ) {
+ fFacetsDefined |= FACET_WHITESPACE;
+ fWhiteSpace = fBase.fWhiteSpace;
+ whiteSpaceAnnotation = fBase.whiteSpaceAnnotation;
+ }
+ // inherit enumeration
+ if ((fFacetsDefined & FACET_ENUMERATION) == 0 && (fBase.fFacetsDefined & FACET_ENUMERATION) != 0) {
+ fFacetsDefined |= FACET_ENUMERATION;
+ fEnumeration = fBase.fEnumeration;
+ fEnumerationSize = fBase.fEnumerationSize;
+ enumerationAnnotations = fBase.enumerationAnnotations;
+ }
+ // inherit maxExclusive
+ if ((( fBase.fFacetsDefined & FACET_MAXEXCLUSIVE) != 0) &&
+ !((fFacetsDefined & FACET_MAXEXCLUSIVE) != 0) && !((fFacetsDefined & FACET_MAXINCLUSIVE) != 0)) {
+ fFacetsDefined |= FACET_MAXEXCLUSIVE;
+ fMaxExclusive = fBase.fMaxExclusive;
+ maxExclusiveAnnotation = fBase.maxExclusiveAnnotation;
+ }
+ // inherit maxInclusive
+ if ((( fBase.fFacetsDefined & FACET_MAXINCLUSIVE) != 0) &&
+ !((fFacetsDefined & FACET_MAXEXCLUSIVE) != 0) && !((fFacetsDefined & FACET_MAXINCLUSIVE) != 0)) {
+ fFacetsDefined |= FACET_MAXINCLUSIVE;
+ fMaxInclusive = fBase.fMaxInclusive;
+ maxInclusiveAnnotation = fBase.maxInclusiveAnnotation;
+ }
+ // inherit minExclusive
+ if ((( fBase.fFacetsDefined & FACET_MINEXCLUSIVE) != 0) &&
+ !((fFacetsDefined & FACET_MINEXCLUSIVE) != 0) && !((fFacetsDefined & FACET_MININCLUSIVE) != 0)) {
+ fFacetsDefined |= FACET_MINEXCLUSIVE;
+ fMinExclusive = fBase.fMinExclusive;
+ minExclusiveAnnotation = fBase.minExclusiveAnnotation;
+ }
+ // inherit minExclusive
+ if ((( fBase.fFacetsDefined & FACET_MININCLUSIVE) != 0) &&
+ !((fFacetsDefined & FACET_MINEXCLUSIVE) != 0) && !((fFacetsDefined & FACET_MININCLUSIVE) != 0)) {
+ fFacetsDefined |= FACET_MININCLUSIVE;
+ fMinInclusive = fBase.fMinInclusive;
+ minInclusiveAnnotation = fBase.minInclusiveAnnotation;
+ }
+ // inherit totalDigits
+ if ((( fBase.fFacetsDefined & FACET_TOTALDIGITS) != 0) &&
+ !((fFacetsDefined & FACET_TOTALDIGITS) != 0)) {
+ fFacetsDefined |= FACET_TOTALDIGITS;
+ fTotalDigits = fBase.fTotalDigits;
+ totalDigitsAnnotation = fBase.totalDigitsAnnotation;
+ }
+ // inherit fractionDigits
+ if ((( fBase.fFacetsDefined & FACET_FRACTIONDIGITS) != 0)
+ && !((fFacetsDefined & FACET_FRACTIONDIGITS) != 0)) {
+ fFacetsDefined |= FACET_FRACTIONDIGITS;
+ fFractionDigits = fBase.fFractionDigits;
+ fractionDigitsAnnotation = fBase.fractionDigitsAnnotation;
+ }
+ //inherit tokeytype
+ if ((fPatternType == SPECIAL_PATTERN_NONE ) && (fBase.fPatternType != SPECIAL_PATTERN_NONE)) {
+ fPatternType = fBase.fPatternType ;
+ }
+
+ // step 5: mark fixed values
+ fFixedFacet |= fBase.fFixedFacet;
+
+ //step 6: setting fundamental facets
+ calcFundamentalFacets();
+
+ } //applyFacets()
+
+ /**
+ * validate a value, and return the compiled form
+ */
+ public Object validate(String content, ValidationContext context, ValidatedInfo validatedInfo) throws InvalidDatatypeValueException {
+
+ if (context == null)
+ context = fEmptyContext;
+
+ if (validatedInfo == null)
+ validatedInfo = new ValidatedInfo();
+ else
+ validatedInfo.memberType = null;
+
+ // first normalize string value, and convert it to actual value
+ boolean needNormalize = context==null||context.needToNormalize();
+ Object ob = getActualValue(content, context, validatedInfo, needNormalize);
+
+ validate(context, validatedInfo);
+
+ return ob;
+
+ }
+
+ protected ValidatedInfo getActualEnumValue(String lexical, ValidationContext ctx, ValidatedInfo info)
+ throws InvalidDatatypeValueException {
+ return fBase.validateWithInfo(lexical, ctx, info);
+ }
+
+ /**
+ * validate a value, and return the compiled form
+ */
+ public ValidatedInfo validateWithInfo(String content, ValidationContext context, ValidatedInfo validatedInfo) throws InvalidDatatypeValueException {
+
+ if (context == null)
+ context = fEmptyContext;
+
+ if (validatedInfo == null)
+ validatedInfo = new ValidatedInfo();
+ else
+ validatedInfo.memberType = null;
+
+ // first normalize string value, and convert it to actual value
+ boolean needNormalize = context==null||context.needToNormalize();
+ getActualValue(content, context, validatedInfo, needNormalize);
+
+ validate(context, validatedInfo);
+
+ return validatedInfo;
+
+ }
+
+ /**
+ * validate a value, and return the compiled form
+ */
+ public Object validate(Object content, ValidationContext context, ValidatedInfo validatedInfo) throws InvalidDatatypeValueException {
+
+ if (context == null)
+ context = fEmptyContext;
+
+ if (validatedInfo == null)
+ validatedInfo = new ValidatedInfo();
+ else
+ validatedInfo.memberType = null;
+
+ // first normalize string value, and convert it to actual value
+ boolean needNormalize = context==null||context.needToNormalize();
+ Object ob = getActualValue(content, context, validatedInfo, needNormalize);
+
+ validate(context, validatedInfo);
+
+ return ob;
+
+ }
+
+ /**
+ * validate an actual value against this DV
+ *
+ * @param context the validation context
+ * @param validatedInfo used to provide the actual value and member types
+ */
+ public void validate(ValidationContext context, ValidatedInfo validatedInfo)
+ throws InvalidDatatypeValueException {
+
+ if (context == null)
+ context = fEmptyContext;
+
+ // then validate the actual value against the facets
+ if (context.needFacetChecking() &&
+ (fFacetsDefined != 0 && fFacetsDefined != FACET_WHITESPACE)) {
+ checkFacets(validatedInfo);
+ }
+
+ // now check extra rules: for ID/IDREF/ENTITY
+ if (context.needExtraChecking()) {
+ checkExtraRules(context, validatedInfo);
+ }
+
+ }
+
+ private void checkFacets(ValidatedInfo validatedInfo) throws InvalidDatatypeValueException {
+
+ Object ob = validatedInfo.actualValue;
+ String content = validatedInfo.normalizedValue;
+ short type = validatedInfo.actualValueType;
+ ShortList itemType = validatedInfo.itemValueTypes;
+
+ // For QName and NOTATION types, we don't check length facets
+ if (fValidationDV != DV_QNAME && fValidationDV != DV_NOTATION) {
+ int length = fDVs[fValidationDV].getDataLength(ob);
+
+ // maxLength
+ if ( (fFacetsDefined & FACET_MAXLENGTH) != 0 ) {
+ if ( length > fMaxLength ) {
+ throw new InvalidDatatypeValueException("cvc-maxLength-valid",
+ new Object[]{content, Integer.toString(length), Integer.toString(fMaxLength), fTypeName});
+ }
+ }
+
+ //minLength
+ if ( (fFacetsDefined & FACET_MINLENGTH) != 0 ) {
+ if ( length < fMinLength ) {
+ throw new InvalidDatatypeValueException("cvc-minLength-valid",
+ new Object[]{content, Integer.toString(length), Integer.toString(fMinLength), fTypeName});
+ }
+ }
+
+ //length
+ if ( (fFacetsDefined & FACET_LENGTH) != 0 ) {
+ if ( length != fLength ) {
+ throw new InvalidDatatypeValueException("cvc-length-valid",
+ new Object[]{content, Integer.toString(length), Integer.toString(fLength), fTypeName});
+ }
+ }
+ }
+
+ //enumeration
+ if ( ((fFacetsDefined & FACET_ENUMERATION) != 0 ) ) {
+ boolean present = false;
+ final int enumSize = fEnumerationSize;
+ final short primitiveType1 = convertToPrimitiveKind(type);
+ for (int i = 0; i < enumSize; i++) {
+ final short primitiveType2 = convertToPrimitiveKind(fEnumeration[i].actualValueType);
+ if ((primitiveType1 == primitiveType2 ||
+ primitiveType1 == XSConstants.ANYSIMPLETYPE_DT && primitiveType2 == XSConstants.STRING_DT ||
+ primitiveType1 == XSConstants.STRING_DT && primitiveType2 == XSConstants.ANYSIMPLETYPE_DT)
+ && fEnumeration[i].actualValue.equals(ob)) {
+ if (primitiveType1 == XSConstants.LIST_DT || primitiveType1 == XSConstants.LISTOFUNION_DT) {
+ ShortList enumItemType = fEnumeration[i].itemValueTypes;
+ final int typeList1Length = itemType != null ? itemType.getLength() : 0;
+ final int typeList2Length = enumItemType != null ? enumItemType.getLength() : 0;
+ if (typeList1Length == typeList2Length) {
+ int j;
+ for (j = 0; j < typeList1Length; ++j) {
+ final short primitiveItem1 = convertToPrimitiveKind(itemType.item(j));
+ final short primitiveItem2 = convertToPrimitiveKind(enumItemType.item(j));
+ if (primitiveItem1 != primitiveItem2) {
+ if (primitiveItem1 == XSConstants.ANYSIMPLETYPE_DT && primitiveItem2 == XSConstants.STRING_DT ||
+ primitiveItem1 == XSConstants.STRING_DT && primitiveItem2 == XSConstants.ANYSIMPLETYPE_DT) {
+ continue;
+ }
+ break;
+ }
+ }
+ if (j == typeList1Length) {
+ present = true;
+ break;
+ }
+ }
+ }
+ else {
+ present = true;
+ break;
+ }
+ }
+ }
+ if(!present){
+ StringBuffer sb = new StringBuffer();
+ appendEnumString(sb);
+ throw new InvalidDatatypeValueException("cvc-enumeration-valid",
+ new Object [] {content, sb.toString()});
+ }
+ }
+
+ //fractionDigits
+ if ((fFacetsDefined & FACET_FRACTIONDIGITS) != 0) {
+ int scale = fDVs[fValidationDV].getFractionDigits(ob);
+ if (scale > fFractionDigits) {
+ throw new InvalidDatatypeValueException("cvc-fractionDigits-valid",
+ new Object[] {content, Integer.toString(scale), Integer.toString(fFractionDigits)});
+ }
+ }
+
+ //totalDigits
+ if ((fFacetsDefined & FACET_TOTALDIGITS)!=0) {
+ int totalDigits = fDVs[fValidationDV].getTotalDigits(ob);
+ if (totalDigits > fTotalDigits) {
+ throw new InvalidDatatypeValueException("cvc-totalDigits-valid",
+ new Object[] {content, Integer.toString(totalDigits), Integer.toString(fTotalDigits)});
+ }
+ }
+
+ int compare;
+
+ //maxinclusive
+ if ( (fFacetsDefined & FACET_MAXINCLUSIVE) != 0 ) {
+ compare = fDVs[fValidationDV].compare(ob, fMaxInclusive);
+ if (compare != -1 && compare != 0) {
+ throw new InvalidDatatypeValueException("cvc-maxInclusive-valid",
+ new Object[] {content, fMaxInclusive, fTypeName});
+ }
+ }
+
+ //maxExclusive
+ if ( (fFacetsDefined & FACET_MAXEXCLUSIVE) != 0 ) {
+ compare = fDVs[fValidationDV].compare(ob, fMaxExclusive );
+ if (compare != -1) {
+ throw new InvalidDatatypeValueException("cvc-maxExclusive-valid",
+ new Object[] {content, fMaxExclusive, fTypeName});
+ }
+ }
+
+ //minInclusive
+ if ( (fFacetsDefined & FACET_MININCLUSIVE) != 0 ) {
+ compare = fDVs[fValidationDV].compare(ob, fMinInclusive);
+ if (compare != 1 && compare != 0) {
+ throw new InvalidDatatypeValueException("cvc-minInclusive-valid",
+ new Object[] {content, fMinInclusive, fTypeName});
+ }
+ }
+
+ //minExclusive
+ if ( (fFacetsDefined & FACET_MINEXCLUSIVE) != 0 ) {
+ compare = fDVs[fValidationDV].compare(ob, fMinExclusive);
+ if (compare != 1) {
+ throw new InvalidDatatypeValueException("cvc-minExclusive-valid",
+ new Object[] {content, fMinExclusive, fTypeName});
+ }
+ }
+
+ }
+
+ private void checkExtraRules(ValidationContext context, ValidatedInfo validatedInfo) throws InvalidDatatypeValueException {
+
+ Object ob = validatedInfo.actualValue;
+
+ if (fVariety == VARIETY_ATOMIC) {
+
+ fDVs[fValidationDV].checkExtraRules(ob, context);
+
+ } else if (fVariety == VARIETY_LIST) {
+
+ ListDV.ListData values = (ListDV.ListData)ob;
+ XSSimpleType memberType = validatedInfo.memberType;
+ int len = values.getLength();
+ try {
+ if (fItemType.fVariety == VARIETY_UNION) {
+ XSSimpleTypeDecl[] memberTypes = (XSSimpleTypeDecl[])validatedInfo.memberTypes;
+ for (int i = len-1; i >= 0; i--) {
+ validatedInfo.actualValue = values.item(i);
+ validatedInfo.memberType = memberTypes[i];
+ fItemType.checkExtraRules(context, validatedInfo);
+ }
+ } else { // (fVariety == VARIETY_ATOMIC)
+ for (int i = len-1; i >= 0; i--) {
+ validatedInfo.actualValue = values.item(i);
+ fItemType.checkExtraRules(context, validatedInfo);
+ }
+ }
+ }
+ finally {
+ validatedInfo.actualValue = values;
+ validatedInfo.memberType = memberType;
+ }
+
+ } else { // (fVariety == VARIETY_UNION)
+
+ ((XSSimpleTypeDecl)validatedInfo.memberType).checkExtraRules(context, validatedInfo);
+
+ }
+
+ }// checkExtraRules()
+
+ //we can still return object for internal use.
+ private Object getActualValue(Object content, ValidationContext context,
+ ValidatedInfo validatedInfo, boolean needNormalize)
+ throws InvalidDatatypeValueException{
+
+ String nvalue;
+ if (needNormalize) {
+ nvalue = normalize(content, fWhiteSpace);
+ } else {
+ nvalue = content.toString();
+ }
+ if ( (fFacetsDefined & FACET_PATTERN ) != 0 ) {
+ RegularExpression regex;
+ for (int idx = fPattern.size()-1; idx >= 0; idx--) {
+ regex = (RegularExpression)fPattern.elementAt(idx);
+ if (!regex.matches(nvalue)){
+ throw new InvalidDatatypeValueException("cvc-pattern-valid",
+ new Object[]{content,
+ fPatternStr.elementAt(idx),
+
+ fTypeName});
+ }
+ }
+ }
+
+ if (fVariety == VARIETY_ATOMIC) {
+
+ // validate special kinds of token, in place of old pattern matching
+ if (fPatternType != SPECIAL_PATTERN_NONE) {
+
+ boolean seenErr = false;
+ if (fPatternType == SPECIAL_PATTERN_NMTOKEN) {
+ // PATTERN "\\c+"
+ seenErr = !XMLChar.isValidNmtoken(nvalue);
+ }
+ else if (fPatternType == SPECIAL_PATTERN_NAME) {
+ // PATTERN "\\i\\c*"
+ seenErr = !XMLChar.isValidName(nvalue);
+ }
+ else if (fPatternType == SPECIAL_PATTERN_NCNAME) {
+ // PATTERN "[\\i-[:]][\\c-[:]]*"
+ seenErr = !XMLChar.isValidNCName(nvalue);
+ }
+ if (seenErr) {
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1",
+ new Object[]{nvalue, SPECIAL_PATTERN_STRING[fPatternType]});
+ }
+ }
+
+ validatedInfo.normalizedValue = nvalue;
+ Object avalue = fDVs[fValidationDV].getActualValue(nvalue, context);
+ validatedInfo.actualValue = avalue;
+ validatedInfo.actualValueType = fBuiltInKind;
+ validatedInfo.actualType = this;
+
+ return avalue;
+
+ } else if (fVariety == VARIETY_LIST) {
+
+ StringTokenizer parsedList = new StringTokenizer(nvalue, " ");
+ int countOfTokens = parsedList.countTokens() ;
+ Object[] avalue = new Object[countOfTokens];
+ boolean isUnion = fItemType.getVariety() == VARIETY_UNION;
+ short[] itemTypes = new short[isUnion ? countOfTokens : 1];
+ if (!isUnion)
+ itemTypes[0] = fItemType.fBuiltInKind;
+ XSSimpleTypeDecl[] memberTypes = new XSSimpleTypeDecl[countOfTokens];
+ for(int i = 0 ; i < countOfTokens ; i ++){
+ // we can't call fItemType.validate(), otherwise checkExtraRules()
+ // will be called twice: once in fItemType.validate, once in
+ // validate method of this type.
+ // so we take two steps to get the actual value:
+ // 1. fItemType.getActualValue()
+ // 2. fItemType.chekcFacets()
+ avalue[i] = fItemType.getActualValue(parsedList.nextToken(), context, validatedInfo, false);
+ if (context.needFacetChecking() &&
+ (fItemType.fFacetsDefined != 0 && fItemType.fFacetsDefined != FACET_WHITESPACE)) {
+ fItemType.checkFacets(validatedInfo);
+ }
+ memberTypes[i] = (XSSimpleTypeDecl)validatedInfo.memberType;
+ if (isUnion)
+ itemTypes[i] = memberTypes[i].fBuiltInKind;
+ }
+
+ ListDV.ListData v = new ListDV.ListData(avalue);
+ validatedInfo.actualValue = v;
+ validatedInfo.actualValueType = isUnion ? XSConstants.LISTOFUNION_DT : XSConstants.LIST_DT;
+ validatedInfo.memberType = null;
+ validatedInfo.memberTypes = memberTypes;
+ validatedInfo.itemValueTypes = new ShortListImpl(itemTypes, itemTypes.length);
+ validatedInfo.normalizedValue = nvalue;
+ // Need to set it here or it will become the item type
+ validatedInfo.actualType = this;
+
+ return v;
+
+ } else { // (fVariety == VARIETY_UNION)
+ final Object _content = (fMemberTypes.length > 1 && content != null) ? content.toString() : content;
+ for (int i = 0; i < fMemberTypes.length; i++) {
+ try {
+ // we can't call fMemberType[i].validate(), otherwise checkExtraRules()
+ // will be called twice: once in fMemberType[i].validate, once in
+ // validate method of this type.
+ // so we take two steps to get the actual value:
+ // 1. fMemberType[i].getActualValue()
+ // 2. fMemberType[i].chekcFacets()
+ Object aValue = fMemberTypes[i].getActualValue(_content, context, validatedInfo, true);
+ if (context.needFacetChecking() &&
+ (fMemberTypes[i].fFacetsDefined != 0 && fMemberTypes[i].fFacetsDefined != FACET_WHITESPACE)) {
+ fMemberTypes[i].checkFacets(validatedInfo);
+ }
+ validatedInfo.memberType = fMemberTypes[i];
+ // Need to set it here or it will become the member type
+ validatedInfo.actualType = this;
+ return aValue;
+ } catch(InvalidDatatypeValueException invalidValue) {
+ }
+ }
+ StringBuffer typesBuffer = new StringBuffer();
+ XSSimpleTypeDecl decl;
+ for(int i = 0;i < fMemberTypes.length; i++) {
+ if(i != 0)
+ typesBuffer.append(" | ");
+ decl = fMemberTypes[i];
+ if(decl.fTargetNamespace != null) {
+ typesBuffer.append('{');
+ typesBuffer.append(decl.fTargetNamespace);
+ typesBuffer.append('}');
+ }
+ typesBuffer.append(decl.fTypeName);
+ if(decl.fEnumeration != null) {
+ typesBuffer.append(" : ");
+ decl.appendEnumString(typesBuffer);
+ }
+ }
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.3",
+ new Object[]{content, fTypeName, typesBuffer.toString()});
+ }
+
+ }//getActualValue()
+
+ public boolean isEqual(Object value1, Object value2) {
+ if (value1 == null) {
+ return false;
+ }
+ return value1.equals(value2);
+ }//isEqual()
+
+ // determine whether the two values are identical
+ public boolean isIdentical (Object value1, Object value2) {
+ if (value1 == null) {
+ return false;
+ }
+ return fDVs[fValidationDV].isIdentical(value1, value2);
+ }//isIdentical()
+
+ // normalize the string according to the whiteSpace facet
+ public static String normalize(String content, short ws) {
+ int len = content == null ? 0 : content.length();
+ if (len == 0 || ws == WS_PRESERVE)
+ return content;
+
+ StringBuffer sb = new StringBuffer();
+ if (ws == WS_REPLACE) {
+ char ch;
+ // when it's replace, just replace #x9, #xa, #xd by #x20
+ for (int i = 0; i < len; i++) {
+ ch = content.charAt(i);
+ if (ch != 0x9 && ch != 0xa && ch != 0xd)
+ sb.append(ch);
+ else
+ sb.append((char)0x20);
+ }
+ } else {
+ char ch;
+ int i;
+ boolean isLeading = true;
+ // when it's collapse
+ for (i = 0; i < len; i++) {
+ ch = content.charAt(i);
+ // append real characters, so we passed leading ws
+ if (ch != 0x9 && ch != 0xa && ch != 0xd && ch != 0x20) {
+ sb.append(ch);
+ isLeading = false;
+ }
+ else {
+ // for whitespaces, we skip all following ws
+ for (; i < len-1; i++) {
+ ch = content.charAt(i+1);
+ if (ch != 0x9 && ch != 0xa && ch != 0xd && ch != 0x20)
+ break;
+ }
+ // if it's not a leading or tailing ws, then append a space
+ if (i < len - 1 && !isLeading)
+ sb.append((char)0x20);
+ }
+ }
+ }
+
+ return sb.toString();
+ }
+
+ // normalize the string according to the whiteSpace facet
+ protected String normalize(Object content, short ws) {
+ if (content == null)
+ return null;
+
+ // If pattern is not defined, we can skip some of the normalization.
+ // Otherwise we have to normalize the data for correct result of
+ // pattern validation.
+ if ( (fFacetsDefined & FACET_PATTERN ) == 0 ) {
+ short norm_type = fDVNormalizeType[fValidationDV];
+ if (norm_type == NORMALIZE_NONE) {
+ return content.toString();
+ }
+ else if (norm_type == NORMALIZE_TRIM) {
+ return XMLChar.trim(content.toString());
+ }
+ }
+
+ if (!(content instanceof StringBuffer)) {
+ String strContent = content.toString();
+ return normalize(strContent, ws);
+ }
+
+ StringBuffer sb = (StringBuffer)content;
+ int len = sb.length();
+ if (len == 0)
+ return "";
+ if (ws == WS_PRESERVE)
+ return sb.toString();
+
+ if (ws == WS_REPLACE) {
+ char ch;
+ // when it's replace, just replace #x9, #xa, #xd by #x20
+ for (int i = 0; i < len; i++) {
+ ch = sb.charAt(i);
+ if (ch == 0x9 || ch == 0xa || ch == 0xd)
+ sb.setCharAt(i, (char)0x20);
+ }
+ } else {
+ char ch;
+ int i, j = 0;
+ boolean isLeading = true;
+ // when it's collapse
+ for (i = 0; i < len; i++) {
+ ch = sb.charAt(i);
+ // append real characters, so we passed leading ws
+ if (ch != 0x9 && ch != 0xa && ch != 0xd && ch != 0x20) {
+ sb.setCharAt(j++, ch);
+ isLeading = false;
+ }
+ else {
+ // for whitespaces, we skip all following ws
+ for (; i < len-1; i++) {
+ ch = sb.charAt(i+1);
+ if (ch != 0x9 && ch != 0xa && ch != 0xd && ch != 0x20)
+ break;
+ }
+ // if it's not a leading or tailing ws, then append a space
+ if (i < len - 1 && !isLeading)
+ sb.setCharAt(j++, (char)0x20);
+ }
+ }
+ sb.setLength(j);
+ }
+
+ return sb.toString();
+ }
+
+ void reportError(String key, Object[] args) throws InvalidDatatypeFacetException {
+ throw new InvalidDatatypeFacetException(key, args);
+ }
+
+
+ private String whiteSpaceValue(short ws){
+ return WS_FACET_STRING[ws];
+ }
+
+ /**
+ * Fundamental Facet: ordered.
+ */
+ public short getOrdered() {
+ return fOrdered;
+ }
+
+ /**
+ * Fundamental Facet: bounded.
+ */
+ public boolean getBounded(){
+ return fBounded;
+ }
+
+ /**
+ * Fundamental Facet: cardinality.
+ */
+ public boolean getFinite(){
+ return fFinite;
+ }
+
+ /**
+ * Fundamental Facet: numeric.
+ */
+ public boolean getNumeric(){
+ return fNumeric;
+ }
+
+ /**
+ * Convenience method. [Facets]: check whether a facet is defined on this
+ * type.
+ * @param facetName The name of the facet.
+ * @return True if the facet is defined, false otherwise.
+ */
+ public boolean isDefinedFacet(short facetName) {
+ if (fValidationDV == DV_ANYSIMPLETYPE ||
+ fValidationDV == DV_ANYATOMICTYPE) {
+ return false;
+ }
+ if ((fFacetsDefined & facetName) != 0) {
+ return true;
+ }
+ if (fPatternType != SPECIAL_PATTERN_NONE) {
+ return facetName == FACET_PATTERN;
+ }
+ if (fValidationDV == DV_INTEGER) {
+ return facetName == FACET_PATTERN || facetName == FACET_FRACTIONDIGITS;
+ }
+ return false;
+ }
+
+ /**
+ * [facets]: all facets defined on this type. The value is a bit
+ * combination of FACET_XXX constants of all defined facets.
+ */
+ public short getDefinedFacets() {
+ if (fValidationDV == DV_ANYSIMPLETYPE ||
+ fValidationDV == DV_ANYATOMICTYPE) {
+ return FACET_NONE;
+ }
+ if (fPatternType != SPECIAL_PATTERN_NONE) {
+ return (short)(fFacetsDefined | FACET_PATTERN);
+ }
+ if (fValidationDV == DV_INTEGER) {
+ return (short)(fFacetsDefined | FACET_PATTERN | FACET_FRACTIONDIGITS);
+ }
+ return fFacetsDefined;
+ }
+
+ /**
+ * Convenience method. [Facets]: check whether a facet is defined and
+ * fixed on this type.
+ * @param facetName The name of the facet.
+ * @return True if the facet is fixed, false otherwise.
+ */
+ public boolean isFixedFacet(short facetName) {
+ if ((fFixedFacet & facetName) != 0)
+ return true;
+ if (fValidationDV == DV_INTEGER)
+ return facetName == FACET_FRACTIONDIGITS;
+ return false;
+ }
+
+ /**
+ * [facets]: all defined facets for this type which are fixed.
+ */
+ public short getFixedFacets() {
+ if (fValidationDV == DV_INTEGER)
+ return (short)(fFixedFacet | FACET_FRACTIONDIGITS);
+ return fFixedFacet;
+ }
+
+ /**
+ * Convenience method. Returns a value of a single constraining facet for
+ * this simple type definition. This method must not be used to retrieve
+ * values for enumeration and pattern facets.
+ * @param facetName The name of the facet, i.e.
+ * FACET_LENGTH, FACET_TOTALDIGITS (see
+ * XSConstants ). To retrieve the value for a pattern or
+ * an enumeration, see enumeration and
+ * pattern .
+ * @return A value of the facet specified in facetName for
+ * this simple type definition or null .
+ */
+ public String getLexicalFacetValue(short facetName) {
+ switch (facetName) {
+ case FACET_LENGTH:
+ return (fLength == -1)?null:Integer.toString(fLength);
+ case FACET_MINLENGTH:
+ return (fMinLength == -1)?null:Integer.toString(fMinLength);
+ case FACET_MAXLENGTH:
+ return (fMaxLength == -1)?null:Integer.toString(fMaxLength);
+ case FACET_WHITESPACE:
+ if (fValidationDV == DV_ANYSIMPLETYPE ||
+ fValidationDV == DV_ANYATOMICTYPE) {
+ return null;
+ }
+ return WS_FACET_STRING[fWhiteSpace];
+ case FACET_MAXINCLUSIVE:
+ return (fMaxInclusive == null)?null:fMaxInclusive.toString();
+ case FACET_MAXEXCLUSIVE:
+ return (fMaxExclusive == null)?null:fMaxExclusive.toString();
+ case FACET_MINEXCLUSIVE:
+ return (fMinExclusive == null)?null:fMinExclusive.toString();
+ case FACET_MININCLUSIVE:
+ return (fMinInclusive == null)?null:fMinInclusive.toString();
+ case FACET_TOTALDIGITS:
+ return (fTotalDigits == -1)?null:Integer.toString(fTotalDigits);
+ case FACET_FRACTIONDIGITS:
+ if (fValidationDV == DV_INTEGER) {
+ return "0";
+ }
+ return (fFractionDigits == -1)?null:Integer.toString(fFractionDigits);
+ }
+ return null;
+ }
+
+ /**
+ * A list of enumeration values if it exists, otherwise an empty
+ * StringList .
+ */
+ public StringList getLexicalEnumeration() {
+ if (fLexicalEnumeration == null){
+ if (fEnumeration == null)
+ return StringListImpl.EMPTY_LIST;
+ int size = fEnumerationSize;
+ String[] strs = new String[size];
+ for (int i = 0; i < size; i++)
+ strs[i] = fEnumeration[i].normalizedValue;
+ fLexicalEnumeration = new StringListImpl(strs, size);
+ }
+ return fLexicalEnumeration;
+ }
+
+ /**
+ * A list of actual enumeration values if it exists, otherwise an empty
+ * ObjectList .
+ */
+ public ObjectList getActualEnumeration() {
+ if (fActualEnumeration == null) {
+ fActualEnumeration = new AbstractObjectList() {
+ public int getLength() {
+ return (fEnumeration != null) ? fEnumerationSize : 0;
+ }
+ public boolean contains(Object item) {
+ if (fEnumeration == null) {
+ return false;
+ }
+ for (int i = 0; i < fEnumerationSize; i++) {
+ if (fEnumeration[i].getActualValue().equals(item)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ public Object item(int index) {
+ if (index < 0 || index >= getLength()) {
+ return null;
+ }
+ return fEnumeration[index].getActualValue();
+ }
+ };
+ }
+ return fActualEnumeration;
+ }
+
+ /**
+ * A list of enumeration type values (as a list of ShortList objects) if it exists, otherwise returns
+ * null
+ */
+ public ObjectList getEnumerationItemTypeList() {
+ if (fEnumerationItemTypeList == null) {
+ if (fEnumeration == null) {
+ return null;
+ }
+ fEnumerationItemTypeList = new AbstractObjectList() {
+ public int getLength() {
+ return (fEnumeration != null) ? fEnumerationSize : 0;
+ }
+ public boolean contains(Object item) {
+ if (fEnumeration == null || !(item instanceof ShortList))
+ return false;
+ for (int i = 0;i < fEnumerationSize; i++)
+ if (fEnumeration[i].itemValueTypes == item)
+ return true;
+ return false;
+ }
+ public Object item(int index) {
+ if (index < 0 || index >= getLength()) {
+ return null;
+ }
+ return fEnumeration[index].itemValueTypes;
+ }
+ };
+ }
+ return fEnumerationItemTypeList;
+ }
+
+ public ShortList getEnumerationTypeList() {
+ if (fEnumerationTypeList == null) {
+ if (fEnumeration == null) {
+ return ShortListImpl.EMPTY_LIST;
+ }
+ short[] list = new short[fEnumerationSize];
+ for (int i = 0; i < fEnumerationSize; i++) {
+ list[i] = fEnumeration[i].actualValueType;
+ }
+ fEnumerationTypeList = new ShortListImpl(list, fEnumerationSize);
+ }
+ return fEnumerationTypeList;
+ }
+
+ /**
+ * A list of pattern values if it exists, otherwise an empty
+ * StringList .
+ */
+ public StringList getLexicalPattern() {
+ if (fPatternType == SPECIAL_PATTERN_NONE && fValidationDV != DV_INTEGER && fPatternStr == null)
+ return StringListImpl.EMPTY_LIST;
+ if (fLexicalPattern == null){
+ int size = fPatternStr == null ? 0 : fPatternStr.size();
+ String[] strs;
+ if (fPatternType == SPECIAL_PATTERN_NMTOKEN) {
+ strs = new String[size+1];
+ strs[size] = "\\c+";
+ }
+ else if (fPatternType == SPECIAL_PATTERN_NAME) {
+ strs = new String[size+1];
+ strs[size] = "\\i\\c*";
+ }
+ else if (fPatternType == SPECIAL_PATTERN_NCNAME) {
+ strs = new String[size+2];
+ strs[size] = "\\i\\c*";
+ strs[size+1] = "[\\i-[:]][\\c-[:]]*";
+ }
+ else if (fValidationDV == DV_INTEGER) {
+ strs = new String[size+1];
+ strs[size] = "[\\-+]?[0-9]+";
+ }
+ else {
+ strs = new String[size];
+ }
+ for (int i = 0; i < size; i++)
+ strs[i] = (String)fPatternStr.elementAt(i);
+ fLexicalPattern = new StringListImpl(strs, strs.length);
+ }
+ return fLexicalPattern;
+ }
+
+ /**
+ * [annotations]: a set of annotations for this simple type component if
+ * it exists, otherwise an empty XSObjectList .
+ */
+ public XSObjectList getAnnotations() {
+ return (fAnnotations != null) ? fAnnotations : XSObjectListImpl.EMPTY_LIST;
+ }
+
+ private void calcFundamentalFacets() {
+ setOrdered();
+ setNumeric();
+ setBounded();
+ setCardinality();
+ }
+
+ private void setOrdered(){
+
+ // When {variety} is atomic, {value} is inherited from {value} of {base type definition}. For all "primitive" types {value} is as specified in the table in Fundamental Facets (C.1).
+ if(fVariety == VARIETY_ATOMIC){
+ this.fOrdered = fBase.fOrdered;
+ }
+
+ // When {variety} is list, {value} is false.
+ else if(fVariety == VARIETY_LIST){
+ this.fOrdered = ORDERED_FALSE;
+ }
+
+ // When {variety} is union, the {value} is partial unless one of the following:
+ // 1. If every member of {member type definitions} is derived from a common ancestor other than the simple ur-type, then {value} is the same as that ancestor's ordered facet.
+ // 2. If every member of {member type definitions} has a {value} of false for the ordered facet, then {value} is false.
+ else if(fVariety == VARIETY_UNION){
+ int length = fMemberTypes.length;
+ // REVISIT: is the length possible to be 0?
+ if (length == 0) {
+ this.fOrdered = ORDERED_PARTIAL;
+ return;
+ }
+ // we need to process the first member type before entering the loop
+ short ancestorId = getPrimitiveDV(fMemberTypes[0].fValidationDV);
+ boolean commonAnc = ancestorId != DV_ANYSIMPLETYPE;
+ boolean allFalse = fMemberTypes[0].fOrdered == ORDERED_FALSE;
+ // for the other member types, check whether the value is false
+ // and whether they have the same ancestor as the first one
+ for (int i = 1; i < fMemberTypes.length && (commonAnc || allFalse); i++) {
+ if (commonAnc)
+ commonAnc = ancestorId == getPrimitiveDV(fMemberTypes[i].fValidationDV);
+ if (allFalse)
+ allFalse = fMemberTypes[i].fOrdered == ORDERED_FALSE;
+ }
+ if (commonAnc) {
+ // REVISIT: all member types should have the same ordered value
+ // just use the first one. Can we assume this?
+ this.fOrdered = fMemberTypes[0].fOrdered;
+ } else if (allFalse) {
+ this.fOrdered = ORDERED_FALSE;
+ } else {
+ this.fOrdered = ORDERED_PARTIAL;
+ }
+ }
+
+ }//setOrdered
+
+ private void setNumeric(){
+ if(fVariety == VARIETY_ATOMIC){
+ this.fNumeric = fBase.fNumeric;
+ }
+ else if(fVariety == VARIETY_LIST){
+ this.fNumeric = false;
+ }
+ else if(fVariety == VARIETY_UNION){
+ XSSimpleType[] memberTypes = fMemberTypes;
+ for(int i = 0 ; i < memberTypes.length ; i++){
+ if(!memberTypes[i].getNumeric() ){
+ this.fNumeric = false;
+ return;
+ }
+ }
+ this.fNumeric = true;
+ }
+
+ }//setNumeric
+
+ private void setBounded(){
+ if(fVariety == VARIETY_ATOMIC){
+ if( (((this.fFacetsDefined & FACET_MININCLUSIVE) != 0) || ((this.fFacetsDefined & FACET_MINEXCLUSIVE) != 0))
+ && (((this.fFacetsDefined & FACET_MAXINCLUSIVE) != 0) || ((this.fFacetsDefined & FACET_MAXEXCLUSIVE) != 0)) ){
+ this.fBounded = true;
+ }
+ else{
+ this.fBounded = false;
+ }
+ }
+ else if(fVariety == VARIETY_LIST){
+ if( ((this.fFacetsDefined & FACET_LENGTH) != 0 ) || ( ((this.fFacetsDefined & FACET_MINLENGTH) != 0 )
+ && ((this.fFacetsDefined & FACET_MAXLENGTH) != 0 )) ){
+ this.fBounded = true;
+ }
+ else{
+ this.fBounded = false;
+ }
+
+ }
+ else if(fVariety == VARIETY_UNION){
+
+ XSSimpleTypeDecl [] memberTypes = this.fMemberTypes;
+ short ancestorId = 0 ;
+
+ if(memberTypes.length > 0){
+ ancestorId = getPrimitiveDV(memberTypes[0].fValidationDV);
+ }
+
+ for(int i = 0 ; i < memberTypes.length ; i++){
+ if(!memberTypes[i].getBounded() || (ancestorId != getPrimitiveDV(memberTypes[i].fValidationDV)) ){
+ this.fBounded = false;
+ return;
+ }
+ }
+ this.fBounded = true;
+ }
+
+ }//setBounded
+
+ private boolean specialCardinalityCheck(){
+ if( (fBase.fValidationDV == XSSimpleTypeDecl.DV_DATE) || (fBase.fValidationDV == XSSimpleTypeDecl.DV_GYEARMONTH)
+ || (fBase.fValidationDV == XSSimpleTypeDecl.DV_GYEAR) || (fBase.fValidationDV == XSSimpleTypeDecl.DV_GMONTHDAY)
+ || (fBase.fValidationDV == XSSimpleTypeDecl.DV_GDAY) || (fBase.fValidationDV == XSSimpleTypeDecl.DV_GMONTH) ){
+ return true;
+ }
+ return false;
+
+ } //specialCardinalityCheck()
+
+ private void setCardinality(){
+ if(fVariety == VARIETY_ATOMIC){
+ if(fBase.fFinite){
+ this.fFinite = true;
+ }
+ else {// (!fBase.fFinite)
+ if ( ((this.fFacetsDefined & FACET_LENGTH) != 0 ) || ((this.fFacetsDefined & FACET_MAXLENGTH) != 0 )
+ || ((this.fFacetsDefined & FACET_TOTALDIGITS) != 0 ) ){
+ this.fFinite = true;
+ }
+ else if( (((this.fFacetsDefined & FACET_MININCLUSIVE) != 0 ) || ((this.fFacetsDefined & FACET_MINEXCLUSIVE) != 0 ))
+ && (((this.fFacetsDefined & FACET_MAXINCLUSIVE) != 0 ) || ((this.fFacetsDefined & FACET_MAXEXCLUSIVE) != 0 )) ){
+ if( ((this.fFacetsDefined & FACET_FRACTIONDIGITS) != 0 ) || specialCardinalityCheck()){
+ this.fFinite = true;
+ }
+ else{
+ this.fFinite = false;
+ }
+ }
+ else{
+ this.fFinite = false;
+ }
+ }
+ }
+ else if(fVariety == VARIETY_LIST){
+ if( ((this.fFacetsDefined & FACET_LENGTH) != 0 ) || ( ((this.fFacetsDefined & FACET_MINLENGTH) != 0 )
+ && ((this.fFacetsDefined & FACET_MAXLENGTH) != 0 )) ){
+ this.fFinite = true;
+ }
+ else{
+ this.fFinite = false;
+ }
+
+ }
+ else if(fVariety == VARIETY_UNION){
+ XSSimpleType [] memberTypes = fMemberTypes;
+ for(int i = 0 ; i < memberTypes.length ; i++){
+ if(!(memberTypes[i].getFinite()) ){
+ this.fFinite = false;
+ return;
+ }
+ }
+ this.fFinite = true;
+ }
+
+ }//setCardinality
+
+ private short getPrimitiveDV(short validationDV){
+
+ if (validationDV == DV_ID || validationDV == DV_IDREF || validationDV == DV_ENTITY){
+ return DV_STRING;
+ }
+ else if (validationDV == DV_INTEGER) {
+ return DV_DECIMAL;
+ }
+ else if (Constants.SCHEMA_1_1_SUPPORT && (validationDV == DV_YEARMONTHDURATION || validationDV == DV_DAYTIMEDURATION)) {
+ return DV_DURATION;
+ }
+ else {
+ return validationDV;
+ }
+
+ }//getPrimitiveDV()
+
+ public boolean derivedFromType(XSTypeDefinition ancestor, short derivation) {
+ // REVISIT: implement according to derivation
+
+ // ancestor is null, return false
+ if (ancestor == null) {
+ return false;
+ }
+ // extract the actual XSTypeDefinition if the given ancestor is a delegate.
+ while (ancestor instanceof XSSimpleTypeDelegate) {
+ ancestor = ((XSSimpleTypeDelegate) ancestor).type;
+ }
+ // ancestor is anyType, return true
+ // anyType is the only type whose base type is itself
+ if (ancestor.getBaseType() == ancestor) {
+ return true;
+ }
+ // recursively get base, and compare it with ancestor
+ XSTypeDefinition type = this;
+ while (type != ancestor && // compare with ancestor
+ type != fAnySimpleType) { // reached anySimpleType
+ type = type.getBaseType();
+ }
+ return type == ancestor;
+ }
+
+ public boolean derivedFrom(String ancestorNS, String ancestorName, short derivation) {
+ // REVISIT: implement according to derivation
+
+ // ancestor is null, retur false
+ if (ancestorName == null)
+ return false;
+ // ancestor is anyType, return true
+ if (URI_SCHEMAFORSCHEMA.equals(ancestorNS) &&
+ ANY_TYPE.equals(ancestorName)) {
+ return true;
+ }
+
+ // recursively get base, and compare it with ancestor
+ XSTypeDefinition type = this;
+ while (!(ancestorName.equals(type.getName()) &&
+ ((ancestorNS == null && type.getNamespace() == null) ||
+ (ancestorNS != null && ancestorNS.equals(type.getNamespace())))) && // compare with ancestor
+ type != fAnySimpleType) { // reached anySimpleType
+ type = (XSTypeDefinition)type.getBaseType();
+ }
+
+ return type != fAnySimpleType;
+ }
+
+ /**
+ * Checks if a type is derived from another by restriction, given the name
+ * and namespace. See:
+ * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#TypeInfo-isDerivedFrom
+ *
+ * @param ancestorNS
+ * The namspace of the ancestor type declaration
+ * @param ancestorName
+ * The name of the ancestor type declaration
+ * @param derivationMethod
+ * The derivation method
+ *
+ * @return boolean True if the ancestor type is derived from the reference type by the specifiied derivation method.
+ */
+ public boolean isDOMDerivedFrom(String ancestorNS, String ancestorName, int derivationMethod) {
+
+ // ancestor is null, return false
+ if (ancestorName == null)
+ return false;
+
+ // ancestor is anyType, return true
+ if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(ancestorNS)
+ && SchemaSymbols.ATTVAL_ANYTYPE.equals(ancestorName)
+ && (((derivationMethod & DERIVATION_RESTRICTION) != 0)
+ || (derivationMethod == DERIVATION_ANY))) {
+ return true;
+ }
+
+ // restriction
+ if ((derivationMethod & DERIVATION_RESTRICTION) != 0) {
+ if (isDerivedByRestriction(ancestorNS, ancestorName, this)) {
+ return true;
+ }
+ }
+
+ // list
+ if ((derivationMethod & DERIVATION_LIST) != 0) {
+ if (isDerivedByList(ancestorNS, ancestorName, this)) {
+ return true;
+ }
+ }
+
+ // union
+ if ((derivationMethod & DERIVATION_UNION) != 0) {
+ if (isDerivedByUnion(ancestorNS, ancestorName, this)) {
+ return true;
+ }
+ }
+
+ // extension
+ if (((derivationMethod & DERIVATION_EXTENSION) != 0)
+ && (((derivationMethod & DERIVATION_RESTRICTION) == 0)
+ && ((derivationMethod & DERIVATION_LIST) == 0)
+ && ((derivationMethod & DERIVATION_UNION) == 0))) {
+ return false;
+ }
+
+ // If the value of the parameter is 0 i.e. no bit (corresponding to
+ // restriction, list, extension or union) is set to 1 for the
+ // derivationMethod parameter.
+ if (((derivationMethod & DERIVATION_EXTENSION) == 0)
+ && (((derivationMethod & DERIVATION_RESTRICTION) == 0)
+ && ((derivationMethod & DERIVATION_LIST) == 0)
+ && ((derivationMethod & DERIVATION_UNION) == 0))) {
+ return isDerivedByAny(ancestorNS, ancestorName, this);
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Checks if a type is derived from another by any combination of restriction, list ir union. See:
+ * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#TypeInfo-isDerivedFrom
+ *
+ * @param ancestorNS
+ * The namspace of the ancestor type declaration
+ * @param ancestorName
+ * The name of the ancestor type declaration
+ * @param type
+ * The reference type definition
+ *
+ * @return boolean True if the type is derived by restriciton for the reference type
+ */
+ private boolean isDerivedByAny(String ancestorNS, String ancestorName,
+ XSTypeDefinition type) {
+
+ boolean derivedFrom = false;
+ XSTypeDefinition oldType = null;
+ // for each base, item or member type
+ while (type != null && type != oldType) {
+
+ // If the ancestor type is reached or is the same as this type.
+ if ((ancestorName.equals(type.getName()))
+ && ((ancestorNS == null && type.getNamespace() == null)
+ || (ancestorNS != null && ancestorNS.equals(type.getNamespace())))) {
+ derivedFrom = true;
+ break;
+ }
+
+ // check if derived by restriction or list or union
+ if (isDerivedByRestriction(ancestorNS, ancestorName, type)) {
+ return true;
+ } else if (isDerivedByList(ancestorNS, ancestorName, type)) {
+ return true;
+ } else if (isDerivedByUnion(ancestorNS, ancestorName, type)) {
+ return true;
+ }
+ oldType = type;
+ // get the base, item or member type depending on the variety
+ if (((XSSimpleTypeDecl) type).getVariety() == VARIETY_ABSENT
+ || ((XSSimpleTypeDecl) type).getVariety() == VARIETY_ATOMIC) {
+ type = type.getBaseType();
+ } else if (((XSSimpleTypeDecl) type).getVariety() == VARIETY_UNION) {
+ for (int i = 0; i < ((XSSimpleTypeDecl) type).getMemberTypes().getLength(); i++) {
+ return isDerivedByAny(ancestorNS, ancestorName,
+ (XSTypeDefinition) ((XSSimpleTypeDecl) type)
+ .getMemberTypes().item(i));
+ }
+ } else if (((XSSimpleTypeDecl) type).getVariety() == VARIETY_LIST) {
+ type = ((XSSimpleTypeDecl) type).getItemType();
+ }
+ }
+
+ return derivedFrom;
+ }
+
+ /**
+ * DOM Level 3
+ * Checks if a type is derived from another by restriction. See:
+ * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#TypeInfo-isDerivedFrom
+ *
+ * @param ancestorNS
+ * The namspace of the ancestor type declaration
+ * @param ancestorName
+ * The name of the ancestor type declaration
+ * @param type
+ * The reference type definition
+ *
+ * @return boolean True if the type is derived by restriciton for the
+ * reference type
+ */
+ private boolean isDerivedByRestriction (String ancestorNS, String ancestorName, XSTypeDefinition type) {
+ XSTypeDefinition oldType = null;
+ while (type != null && type != oldType) {
+ if ((ancestorName.equals(type.getName()))
+ && ((ancestorNS != null && ancestorNS.equals(type.getNamespace()))
+ || (type.getNamespace() == null && ancestorNS == null))) {
+
+ return true;
+ }
+ oldType = type;
+ type = type.getBaseType();
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks if a type is derived from another by list. See:
+ * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#TypeInfo-isDerivedFrom
+ *
+ * @param ancestorNS
+ * The namspace of the ancestor type declaration
+ * @param ancestorName
+ * The name of the ancestor type declaration
+ * @param type
+ * The reference type definition
+ *
+ * @return boolean True if the type is derived by list for the reference type
+ */
+ private boolean isDerivedByList (String ancestorNS, String ancestorName, XSTypeDefinition type) {
+ // If the variety is union
+ if (type !=null && ((XSSimpleTypeDefinition)type).getVariety() == VARIETY_LIST) {
+
+ // get the {item type}
+ XSTypeDefinition itemType = ((XSSimpleTypeDefinition)type).getItemType();
+
+ // T2 is the {item type definition}
+ if (itemType != null) {
+
+ // T2 is derived from the other type definition by DERIVATION_RESTRICTION
+ if (isDerivedByRestriction(ancestorNS, ancestorName, itemType)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if a type is derived from another by union. See:
+ * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#TypeInfo-isDerivedFrom
+ *
+ * @param ancestorNS
+ * The namspace of the ancestor type declaration
+ * @param ancestorName
+ * The name of the ancestor type declaration
+ * @param type
+ * The reference type definition
+ *
+ * @return boolean True if the type is derived by union for the reference type
+ */
+ private boolean isDerivedByUnion (String ancestorNS, String ancestorName, XSTypeDefinition type) {
+
+ // If the variety is union
+ if (type !=null && ((XSSimpleTypeDefinition)type).getVariety() == VARIETY_UNION) {
+
+ // get member types
+ XSObjectList memberTypes = ((XSSimpleTypeDefinition)type).getMemberTypes();
+
+ for (int i = 0; i < memberTypes.getLength(); i++) {
+ // One of the {member type definitions} is T2.
+ if (memberTypes.item(i) != null) {
+ // T2 is derived from the other type definition by DERIVATION_RESTRICTION
+ if (isDerivedByRestriction(ancestorNS, ancestorName,(XSSimpleTypeDefinition)memberTypes.item(i))) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+
+ static final XSSimpleTypeDecl fAnySimpleType = new XSSimpleTypeDecl(null, "anySimpleType", DV_ANYSIMPLETYPE, ORDERED_FALSE, false, true, false, true, XSConstants.ANYSIMPLETYPE_DT);
+
+ static final XSSimpleTypeDecl fAnyAtomicType = new XSSimpleTypeDecl(fAnySimpleType, "anyAtomicType", DV_ANYATOMICTYPE, ORDERED_FALSE, false, true, false, true, XSSimpleTypeDecl.ANYATOMICTYPE_DT);
+
+ /**
+ * Validation context used to validate facet values.
+ */
+ static final ValidationContext fDummyContext = new ValidationContext() {
+ public boolean needFacetChecking() {
+ return true;
+ }
+
+ public boolean needExtraChecking() {
+ return false;
+ }
+ public boolean needToNormalize() {
+ return false;
+ }
+ public boolean useNamespaces() {
+ return true;
+ }
+
+ public boolean isEntityDeclared(String name) {
+ return false;
+ }
+
+ public boolean isEntityUnparsed(String name) {
+ return false;
+ }
+
+ public boolean isIdDeclared(String name) {
+ return false;
+ }
+
+ public void addId(String name) {
+ }
+
+ public void addIdRef(String name) {
+ }
+
+ public String getSymbol (String symbol) {
+ return symbol.intern();
+ }
+
+ public String getURI(String prefix) {
+ return null;
+ }
+
+ public Locale getLocale() {
+ return Locale.getDefault();
+ }
+ };
+
+ private boolean fAnonymous = false;
+
+ /**
+ * A wrapper of ValidationContext, to provide a way of switching to a
+ * different Namespace declaration context.
+ */
+ static final class ValidationContextImpl implements ValidationContext {
+
+ final ValidationContext fExternal;
+
+ ValidationContextImpl(ValidationContext external) {
+ fExternal = external;
+ }
+
+ NamespaceContext fNSContext;
+ void setNSContext(NamespaceContext nsContext) {
+ fNSContext = nsContext;
+ }
+
+ public boolean needFacetChecking() {
+ return fExternal.needFacetChecking();
+ }
+
+ public boolean needExtraChecking() {
+ return fExternal.needExtraChecking();
+ }
+ public boolean needToNormalize() {
+ return fExternal.needToNormalize();
+ }
+ // schema validation is predicated upon namespaces
+ public boolean useNamespaces() {
+ return true;
+ }
+
+ public boolean isEntityDeclared (String name) {
+ return fExternal.isEntityDeclared(name);
+ }
+
+ public boolean isEntityUnparsed (String name) {
+ return fExternal.isEntityUnparsed(name);
+ }
+
+ public boolean isIdDeclared (String name) {
+ return fExternal.isIdDeclared(name);
+ }
+
+ public void addId(String name) {
+ fExternal.addId(name);
+ }
+
+ public void addIdRef(String name) {
+ fExternal.addIdRef(name);
+ }
+
+ public String getSymbol (String symbol) {
+ return fExternal.getSymbol(symbol);
+ }
+
+ public String getURI(String prefix) {
+ if (fNSContext == null) {
+ return fExternal.getURI(prefix);
+ }
+ else {
+ return fNSContext.getURI(prefix);
+ }
+ }
+
+ public Locale getLocale() {
+ return fExternal.getLocale();
+ }
+ }
+
+ public void reset(){
+
+ // if it's immutable, can't be reset:
+ if (fIsImmutable) return;
+ fItemType = null;
+ fMemberTypes = null;
+
+ fTypeName = null;
+ fTargetNamespace = null;
+ fFinalSet = 0;
+ fBase = null;
+ fVariety = -1;
+ fValidationDV = -1;
+
+ fFacetsDefined = 0;
+ fFixedFacet = 0;
+
+ //for constraining facets
+ fWhiteSpace = 0;
+ fLength = -1;
+ fMinLength = -1;
+ fMaxLength = -1;
+ fTotalDigits = -1;
+ fFractionDigits = -1;
+ fPattern = null;
+ fPatternStr = null;
+ fEnumeration = null;
+ fLexicalPattern = null;
+ fLexicalEnumeration = null;
+ fActualEnumeration = null;
+ fEnumerationTypeList = null;
+ fEnumerationItemTypeList = null;
+ fMaxInclusive = null;
+ fMaxExclusive = null;
+ fMinExclusive = null;
+ fMinInclusive = null;
+ lengthAnnotation = null;
+ minLengthAnnotation = null;
+ maxLengthAnnotation = null;
+ whiteSpaceAnnotation = null;
+ totalDigitsAnnotation = null;
+ fractionDigitsAnnotation = null;
+ patternAnnotations = null;
+ enumerationAnnotations = null;
+ maxInclusiveAnnotation = null;
+ maxExclusiveAnnotation = null;
+ minInclusiveAnnotation = null;
+ minExclusiveAnnotation = null;
+
+ fPatternType = SPECIAL_PATTERN_NONE;
+ fAnnotations = null;
+ fFacets = null;
+
+ // REVISIT: reset for fundamental facets
+ }
+
+ /**
+ * @see org.apache.xerces.xs.XSObject#getNamespaceItem()
+ */
+ public XSNamespaceItem getNamespaceItem() {
+ return fNamespaceItem;
+ }
+
+ public void setNamespaceItem(XSNamespaceItem namespaceItem) {
+ fNamespaceItem = namespaceItem;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return this.fTargetNamespace+"," +this.fTypeName;
+ }
+
+ /**
+ * A list of constraining facets if it exists, otherwise an empty
+ * XSObjectList . Note: This method must not be used to
+ * retrieve values for enumeration and pattern
+ * facets.
+ */
+ public XSObjectList getFacets() {
+ if (fFacets == null &&
+ (fFacetsDefined != 0 || fValidationDV == DV_INTEGER)) {
+
+ XSFacetImpl[] facets = new XSFacetImpl[10];
+ int count = 0;
+ if ((fFacetsDefined & FACET_WHITESPACE) != 0 &&
+ fValidationDV != DV_ANYSIMPLETYPE &&
+ fValidationDV != DV_ANYATOMICTYPE) {
+ facets[count] =
+ new XSFacetImpl(
+ FACET_WHITESPACE,
+ WS_FACET_STRING[fWhiteSpace],
+ 0,
+ null,
+ (fFixedFacet & FACET_WHITESPACE) != 0,
+ whiteSpaceAnnotation);
+ count++;
+ }
+ if (fLength != -1) {
+ facets[count] =
+ new XSFacetImpl(
+ FACET_LENGTH,
+ Integer.toString(fLength),
+ fLength,
+ null,
+ (fFixedFacet & FACET_LENGTH) != 0,
+ lengthAnnotation);
+ count++;
+ }
+ if (fMinLength != -1) {
+ facets[count] =
+ new XSFacetImpl(
+ FACET_MINLENGTH,
+ Integer.toString(fMinLength),
+ fMinLength,
+ null,
+ (fFixedFacet & FACET_MINLENGTH) != 0,
+ minLengthAnnotation);
+ count++;
+ }
+ if (fMaxLength != -1) {
+ facets[count] =
+ new XSFacetImpl(
+ FACET_MAXLENGTH,
+ Integer.toString(fMaxLength),
+ fMaxLength,
+ null,
+ (fFixedFacet & FACET_MAXLENGTH) != 0,
+ maxLengthAnnotation);
+ count++;
+ }
+ if (fTotalDigits != -1) {
+ facets[count] =
+ new XSFacetImpl(
+ FACET_TOTALDIGITS,
+ Integer.toString(fTotalDigits),
+ fTotalDigits,
+ null,
+ (fFixedFacet & FACET_TOTALDIGITS) != 0,
+ totalDigitsAnnotation);
+ count++;
+ }
+ if (fValidationDV == DV_INTEGER) {
+ facets[count] =
+ new XSFacetImpl(
+ FACET_FRACTIONDIGITS,
+ "0",
+ 0,
+ null,
+ true,
+ fractionDigitsAnnotation);
+ count++;
+ }
+ else if (fFractionDigits != -1) {
+ facets[count] =
+ new XSFacetImpl(
+ FACET_FRACTIONDIGITS,
+ Integer.toString(fFractionDigits),
+ fFractionDigits,
+ null,
+ (fFixedFacet & FACET_FRACTIONDIGITS) != 0,
+ fractionDigitsAnnotation);
+ count++;
+ }
+ if (fMaxInclusive != null) {
+ facets[count] =
+ new XSFacetImpl(
+ FACET_MAXINCLUSIVE,
+ fMaxInclusive.toString(),
+ 0,
+ fMaxInclusive,
+ (fFixedFacet & FACET_MAXINCLUSIVE) != 0,
+ maxInclusiveAnnotation);
+ count++;
+ }
+ if (fMaxExclusive != null) {
+ facets[count] =
+ new XSFacetImpl(
+ FACET_MAXEXCLUSIVE,
+ fMaxExclusive.toString(),
+ 0,
+ fMaxExclusive,
+ (fFixedFacet & FACET_MAXEXCLUSIVE) != 0,
+ maxExclusiveAnnotation);
+ count++;
+ }
+ if (fMinExclusive != null) {
+ facets[count] =
+ new XSFacetImpl(
+ FACET_MINEXCLUSIVE,
+ fMinExclusive.toString(),
+ 0,
+ fMinExclusive,
+ (fFixedFacet & FACET_MINEXCLUSIVE) != 0,
+ minExclusiveAnnotation);
+ count++;
+ }
+ if (fMinInclusive != null) {
+ facets[count] =
+ new XSFacetImpl(
+ FACET_MININCLUSIVE,
+ fMinInclusive.toString(),
+ 0,
+ fMinInclusive,
+ (fFixedFacet & FACET_MININCLUSIVE) != 0,
+ minInclusiveAnnotation);
+ count++;
+ }
+ fFacets = (count > 0) ? new XSObjectListImpl(facets, count) : XSObjectListImpl.EMPTY_LIST;
+ }
+ return (fFacets != null) ? fFacets : XSObjectListImpl.EMPTY_LIST;
+ }
+
+ public XSObject getFacet(int facetType) {
+ if (facetType == FACET_ENUMERATION || facetType == FACET_PATTERN) {
+ XSObjectList list = getMultiValueFacets();
+ for (int i = 0; i < list.getLength(); i++) {
+ XSMultiValueFacet f = (XSMultiValueFacet)list.item(i);
+ if (f.getFacetKind() == facetType) {
+ return f;
+ }
+ }
+ }
+ else {
+ XSObjectList list = getFacets();
+ for (int i = 0; i < list.getLength(); i++) {
+ XSFacet f = (XSFacet)list.item(i);
+ if (f.getFacetKind() == facetType) {
+ return f;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * A list of enumeration and pattern constraining facets if it exists,
+ * otherwise an empty XSObjectList .
+ */
+ public XSObjectList getMultiValueFacets() {
+ if (fMultiValueFacets == null &&
+ ((fFacetsDefined & FACET_ENUMERATION) != 0 ||
+ (fFacetsDefined & FACET_PATTERN) != 0 ||
+ fPatternType != SPECIAL_PATTERN_NONE ||
+ fValidationDV == DV_INTEGER)) {
+
+ XSMVFacetImpl[] facets = new XSMVFacetImpl[2];
+ int count = 0;
+ if ((fFacetsDefined & FACET_PATTERN) != 0 ||
+ fPatternType != SPECIAL_PATTERN_NONE ||
+ fValidationDV == DV_INTEGER) {
+ facets[count] =
+ new XSMVFacetImpl(
+ FACET_PATTERN,
+ this.getLexicalPattern(),
+ null,
+ patternAnnotations);
+ count++;
+ }
+ if (fEnumeration != null) {
+ facets[count] =
+ new XSMVFacetImpl(
+ FACET_ENUMERATION,
+ this.getLexicalEnumeration(),
+ new ObjectListImpl(fEnumeration, fEnumerationSize),
+ enumerationAnnotations);
+ count++;
+ }
+ fMultiValueFacets = new XSObjectListImpl(facets, count);
+ }
+ return (fMultiValueFacets != null) ?
+ fMultiValueFacets : XSObjectListImpl.EMPTY_LIST;
+ }
+
+ public Object getMinInclusiveValue() {
+ return fMinInclusive;
+ }
+
+ public Object getMinExclusiveValue() {
+ return fMinExclusive;
+ }
+
+ public Object getMaxInclusiveValue() {
+ return fMaxInclusive;
+ }
+
+ public Object getMaxExclusiveValue() {
+ return fMaxExclusive;
+ }
+
+ public void setAnonymous(boolean anon) {
+ fAnonymous = anon;
+ }
+
+ private static final class XSFacetImpl implements XSFacet {
+ final short kind;
+ final String svalue;
+ final int ivalue;
+ Object avalue;
+ final boolean fixed;
+ final XSObjectList annotations;
+
+ public XSFacetImpl(short kind, String svalue, int ivalue, Object avalue, boolean fixed, XSAnnotation annotation) {
+ this.kind = kind;
+ this.svalue = svalue;
+ this.ivalue = ivalue;
+ this.avalue = avalue;
+ this.fixed = fixed;
+
+ if (annotation != null) {
+ this.annotations = new XSObjectListImpl();
+ ((XSObjectListImpl)this.annotations).addXSObject(annotation);
+ }
+ else {
+ this.annotations = XSObjectListImpl.EMPTY_LIST;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.xerces.xs.XSFacet#getAnnotation()
+ */
+ /**
+ * Optional. Annotation.
+ */
+ public XSAnnotation getAnnotation() {
+ return (XSAnnotation) annotations.item(0);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.xerces.xs.XSFacet#getAnnotations()
+ */
+ /**
+ * Optional. Annotations.
+ */
+ public XSObjectList getAnnotations() {
+ return annotations;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSFacet#getFacetKind()
+ */
+ public short getFacetKind() {
+ return kind;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSFacet#getLexicalFacetValue()
+ */
+ public String getLexicalFacetValue() {
+ return svalue;
+ }
+
+ public Object getActualFacetValue() {
+ if (avalue == null) {
+ if (kind == FACET_WHITESPACE) {
+ avalue = svalue;
+ }
+ else {
+ // Must a facet with an integer value. Use BigInteger.
+ avalue = BigInteger.valueOf(ivalue);
+ }
+ }
+ return avalue;
+ }
+
+ public int getIntFacetValue() {
+ return ivalue;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSFacet#isFixed()
+ */
+ public boolean getFixed() {
+ return fixed;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSObject#getName()
+ */
+ public String getName() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSObject#getNamespace()
+ */
+ public String getNamespace() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSObject#getNamespaceItem()
+ */
+ public XSNamespaceItem getNamespaceItem() {
+ // REVISIT: implement
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSObject#getType()
+ */
+ public short getType() {
+ return XSConstants.FACET;
+ }
+
+ }
+
+ private static final class XSMVFacetImpl implements XSMultiValueFacet {
+ final short kind;
+ final XSObjectList annotations;
+ final StringList svalues;
+ final ObjectList avalues;
+
+ public XSMVFacetImpl(short kind, StringList svalues, ObjectList avalues, XSObjectList annotations) {
+ this.kind = kind;
+ this.svalues = svalues;
+ this.avalues = avalues;
+ this.annotations = (annotations != null) ? annotations : XSObjectListImpl.EMPTY_LIST;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSFacet#getFacetKind()
+ */
+ public short getFacetKind() {
+ return kind;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSMultiValueFacet#getAnnotations()
+ */
+ public XSObjectList getAnnotations() {
+ return annotations;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSMultiValueFacet#getLexicalFacetValues()
+ */
+ public StringList getLexicalFacetValues() {
+ return svalues;
+ }
+
+ public ObjectList getEnumerationValues() {
+ return avalues;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSObject#getName()
+ */
+ public String getName() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSObject#getNamespace()
+ */
+ public String getNamespace() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSObject#getNamespaceItem()
+ */
+ public XSNamespaceItem getNamespaceItem() {
+ // REVISIT: implement
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.XSObject#getType()
+ */
+ public short getType() {
+ return XSConstants.MULTIVALUE_FACET;
+ }
+ }
+
+ private static abstract class AbstractObjectList extends AbstractList implements ObjectList {
+ public Object get(int index) {
+ if (index >= 0 && index < getLength()) {
+ return item(index);
+ }
+ throw new IndexOutOfBoundsException("Index: " + index);
+ }
+ public int size() {
+ return getLength();
+ }
+ }
+
+ public String getTypeNamespace() {
+ return getNamespace();
+ }
+
+ public boolean isDerivedFrom(String typeNamespaceArg, String typeNameArg, int derivationMethod) {
+ return isDOMDerivedFrom(typeNamespaceArg, typeNameArg, derivationMethod);
+ }
+
+ private short convertToPrimitiveKind(short valueType) {
+ /** Primitive datatypes. */
+ if (valueType <= XSConstants.NOTATION_DT) {
+ return valueType;
+ }
+ /** Types derived from string. */
+ if (valueType <= XSConstants.ENTITY_DT) {
+ return XSConstants.STRING_DT;
+ }
+ /** Types derived from decimal. */
+ if (valueType <= XSConstants.POSITIVEINTEGER_DT) {
+ return XSConstants.DECIMAL_DT;
+ }
+ /** Other types. */
+ return valueType;
+ }
+
+ private void appendEnumString(StringBuffer sb) {
+ sb.append('[');
+ for (int i = 0; i < fEnumerationSize; i++) {
+ if (i != 0) {
+ sb.append(", ");
+ }
+ sb.append(fEnumeration[i].actualValue);
+ }
+ sb.append(']');
+ }
+} // class XSSimpleTypeDecl
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/XSSimpleTypeDelegate.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/XSSimpleTypeDelegate.java
new file mode 100644
index 0000000..d720dc0
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/XSSimpleTypeDelegate.java
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import org.apache.xerces.impl.dv.DatatypeException;
+import org.apache.xerces.impl.dv.InvalidDatatypeFacetException;
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidatedInfo;
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.impl.dv.XSFacets;
+import org.apache.xerces.impl.dv.XSSimpleType;
+import org.apache.xerces.xs.StringList;
+import org.apache.xerces.xs.XSNamespaceItem;
+import org.apache.xerces.xs.XSObject;
+import org.apache.xerces.xs.XSObjectList;
+import org.apache.xerces.xs.XSSimpleTypeDefinition;
+import org.apache.xerces.xs.XSTypeDefinition;
+
+/**
+ * Base class for XSSimpleType wrapper implementations.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class XSSimpleTypeDelegate
+ implements XSSimpleType {
+
+ protected final XSSimpleType type;
+
+ public XSSimpleTypeDelegate(XSSimpleType type) {
+ if (type == null) {
+ throw new NullPointerException();
+ }
+ this.type = type;
+ }
+
+ public XSSimpleType getWrappedXSSimpleType() {
+ return type;
+ }
+
+ public XSObjectList getAnnotations() {
+ return type.getAnnotations();
+ }
+
+ public boolean getBounded() {
+ return type.getBounded();
+ }
+
+ public short getBuiltInKind() {
+ return type.getBuiltInKind();
+ }
+
+ public short getDefinedFacets() {
+ return type.getDefinedFacets();
+ }
+
+ public XSObjectList getFacets() {
+ return type.getFacets();
+ }
+
+ public XSObject getFacet(int facetType) {
+ return type.getFacet(facetType);
+ }
+
+ public boolean getFinite() {
+ return type.getFinite();
+ }
+
+ public short getFixedFacets() {
+ return type.getFixedFacets();
+ }
+
+ public XSSimpleTypeDefinition getItemType() {
+ return type.getItemType();
+ }
+
+ public StringList getLexicalEnumeration() {
+ return type.getLexicalEnumeration();
+ }
+
+ public String getLexicalFacetValue(short facetName) {
+ return type.getLexicalFacetValue(facetName);
+ }
+
+ public StringList getLexicalPattern() {
+ return type.getLexicalPattern();
+ }
+
+ public XSObjectList getMemberTypes() {
+ return type.getMemberTypes();
+ }
+
+ public XSObjectList getMultiValueFacets() {
+ return type.getMultiValueFacets();
+ }
+
+ public boolean getNumeric() {
+ return type.getNumeric();
+ }
+
+ public short getOrdered() {
+ return type.getOrdered();
+ }
+
+ public XSSimpleTypeDefinition getPrimitiveType() {
+ return type.getPrimitiveType();
+ }
+
+ public short getVariety() {
+ return type.getVariety();
+ }
+
+ public boolean isDefinedFacet(short facetName) {
+ return type.isDefinedFacet(facetName);
+ }
+
+ public boolean isFixedFacet(short facetName) {
+ return type.isFixedFacet(facetName);
+ }
+
+ public boolean derivedFrom(String namespace, String name, short derivationMethod) {
+ return type.derivedFrom(namespace, name, derivationMethod);
+ }
+
+ public boolean derivedFromType(XSTypeDefinition ancestorType, short derivationMethod) {
+ return type.derivedFromType(ancestorType, derivationMethod);
+ }
+
+ public boolean getAnonymous() {
+ return type.getAnonymous();
+ }
+
+ public XSTypeDefinition getBaseType() {
+ return type.getBaseType();
+ }
+
+ public short getFinal() {
+ return type.getFinal();
+ }
+
+ public short getTypeCategory() {
+ return type.getTypeCategory();
+ }
+
+ public boolean isFinal(short restriction) {
+ return type.isFinal(restriction);
+ }
+
+ public String getName() {
+ return type.getName();
+ }
+
+ public String getNamespace() {
+ return type.getNamespace();
+ }
+
+ public XSNamespaceItem getNamespaceItem() {
+ return type.getNamespaceItem();
+ }
+
+ public short getType() {
+ return type.getType();
+ }
+
+ public void applyFacets(XSFacets facets, short presentFacet, short fixedFacet, ValidationContext context)
+ throws InvalidDatatypeFacetException {
+ type.applyFacets(facets, presentFacet, fixedFacet, context);
+ }
+
+ public short getPrimitiveKind() {
+ return type.getPrimitiveKind();
+ }
+
+ public short getWhitespace() throws DatatypeException {
+ return type.getWhitespace();
+ }
+
+ public boolean isEqual(Object value1, Object value2) {
+ return type.isEqual(value1, value2);
+ }
+
+ public boolean isIDType() {
+ return type.isIDType();
+ }
+
+ public void validate(ValidationContext context, ValidatedInfo validatedInfo)
+ throws InvalidDatatypeValueException {
+ type.validate(context, validatedInfo);
+ }
+
+ public Object validate(String content, ValidationContext context, ValidatedInfo validatedInfo)
+ throws InvalidDatatypeValueException {
+ return type.validate(content, context, validatedInfo);
+ }
+
+ public Object validate(Object content, ValidationContext context, ValidatedInfo validatedInfo)
+ throws InvalidDatatypeValueException {
+ return type.validate(content, context, validatedInfo);
+ }
+
+ public String toString() {
+ return type.toString();
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/YearDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/YearDV.java
new file mode 100644
index 0000000..d172f2d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/YearDV.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Validator for <gYear> datatype (W3C Schema Datatypes)
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani
+ * @author Gopal Sharma, SUN Microsystem Inc.
+ *
+ * @version $Id$
+ */
+
+public class YearDV extends AbstractDateTimeDV {
+
+ /**
+ * Convert a string to a compiled form
+ *
+ * @param content The lexical representation of time
+ * @return a valid and normalized time object
+ */
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException{
+ try{
+ return parse(content);
+ } catch(Exception ex){
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "gYear"});
+ }
+ }
+
+ /**
+ * Parses, validates and computes normalized version of gYear object
+ *
+ * @param str The lexical representation of year object CCYY
+ * with possible time zone Z or (-),(+)hh:mm
+ * @return normalized date representation
+ * @exception SchemaDateTimeException Invalid lexical representation
+ */
+ protected DateTimeData parse(String str) throws SchemaDateTimeException{
+ DateTimeData date = new DateTimeData(str, this);
+ int len = str.length();
+
+ // check for preceding '-' sign
+ int start = 0;
+ if (str.charAt(0)=='-') {
+ start = 1;
+ }
+ int sign = findUTCSign(str, start, len);
+
+ final int length = ((sign == -1) ? len : sign) - start;
+ if (length < 4) {
+ throw new RuntimeException("Year must have 'CCYY' format");
+ }
+ else if (length > 4 && str.charAt(start) == '0') {
+ throw new RuntimeException("Leading zeros are required if the year value would otherwise have fewer than four digits; otherwise they are forbidden");
+ }
+
+ if (sign == -1) {
+ date.year=parseIntYear(str, len);
+ }
+ else {
+ date.year=parseIntYear(str, sign);
+ getTimeZone (str, date, sign, len);
+ }
+
+ //initialize values
+ date.month=MONTH;
+ date.day=1;
+
+ //validate and normalize
+ validateDateTime(date);
+
+ //save unnormalized values
+ saveUnnormalized(date);
+
+ if ( date.utc!=0 && date.utc!='Z' ) {
+ normalize(date);
+ }
+ date.position = 0;
+ return date;
+ }
+
+ /**
+ * Converts year object representation to String
+ *
+ * @param date year object
+ * @return lexical representation of month: CCYY with optional time zone sign
+ */
+ protected String dateToString(DateTimeData date) {
+ StringBuffer message = new StringBuffer(5);
+ append(message, date.year, 4);
+ append(message, (char)date.utc, 0);
+ return message.toString();
+ }
+
+ protected XMLGregorianCalendar getXMLGregorianCalendar(DateTimeData date) {
+ return datatypeFactory.newXMLGregorianCalendar(date.unNormYear, DatatypeConstants.FIELD_UNDEFINED,
+ DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED,
+ DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED,
+ date.hasTimeZone() ? date.timezoneHr * 60 + date.timezoneMin : DatatypeConstants.FIELD_UNDEFINED);
+ }
+}
+
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/YearMonthDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/YearMonthDV.java
new file mode 100644
index 0000000..acf064f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/YearMonthDV.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Validator for <gYearMonth> datatype (W3C Schema Datatypes)
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani
+ * @author Gopal Sharma, SUN Microsystem Inc.
+ *
+ * @version $Id$
+ */
+public class YearMonthDV extends AbstractDateTimeDV{
+
+ /**
+ * Convert a string to a compiled form
+ *
+ * @param content The lexical representation of gYearMonth
+ * @return a valid and normalized gYearMonth object
+ */
+ public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException{
+ try{
+ return parse(content);
+ } catch(Exception ex){
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "gYearMonth"});
+ }
+ }
+
+ /**
+ * Parses, validates and computes normalized version of gYearMonth object
+ *
+ * @param str The lexical representation of gYearMonth object CCYY-MM
+ * with possible time zone Z or (-),(+)hh:mm
+ * @return normalized date representation
+ * @exception SchemaDateTimeException Invalid lexical representation
+ */
+ protected DateTimeData parse(String str) throws SchemaDateTimeException{
+ DateTimeData date = new DateTimeData(str, this);
+ int len = str.length();
+
+ // get date
+ int end = getYearMonth(str, 0, len, date);
+ date.day = DAY;
+ parseTimeZone (str, end, len, date);
+
+ //validate and normalize
+
+ validateDateTime(date);
+
+ //save unnormalized values
+ saveUnnormalized(date);
+
+ if ( date.utc!=0 && date.utc!='Z' ) {
+ normalize(date);
+ }
+ date.position = 0;
+ return date;
+ }
+
+ protected String dateToString(DateTimeData date) {
+ StringBuffer message = new StringBuffer(25);
+ append(message, date.year, 4);
+ message.append('-');
+ append(message, date.month, 2);
+ append(message, (char)date.utc, 0);
+ return message.toString();
+ }
+
+ protected XMLGregorianCalendar getXMLGregorianCalendar(DateTimeData date) {
+ return datatypeFactory.newXMLGregorianCalendar(date.unNormYear, date.unNormMonth, DatatypeConstants.FIELD_UNDEFINED,
+ DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED,
+ DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED,
+ date.hasTimeZone() ? date.timezoneHr * 60 + date.timezoneMin : DatatypeConstants.FIELD_UNDEFINED);
+ }
+}
+
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/YearMonthDurationDV.java b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/YearMonthDurationDV.java
new file mode 100644
index 0000000..970d6df
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/dv/xs/YearMonthDurationDV.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.dv.xs;
+
+import java.math.BigInteger;
+
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.Duration;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidationContext;
+
+/**
+ * Used to validate the type
+ *
+ * @xerces.internal
+ *
+ * @author Ankit Pasricha, IBM
+ *
+ * @version $Id$
+ */
+class YearMonthDurationDV extends DurationDV {
+
+ public Object getActualValue(String content, ValidationContext context)
+ throws InvalidDatatypeValueException {
+ try {
+ return parse(content, DurationDV.YEARMONTHDURATION_TYPE);
+ }
+ catch (Exception ex) {
+ throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "yearMonthDuration"});
+ }
+ }
+
+ protected Duration getDuration(DateTimeData date) {
+ int sign = 1;
+ if ( date.year<0 || date.month<0) {
+ sign = -1;
+ }
+ return datatypeFactory.newDuration(sign == 1,
+ date.year != DatatypeConstants.FIELD_UNDEFINED?BigInteger.valueOf(sign*date.year):null,
+ date.month != DatatypeConstants.FIELD_UNDEFINED?BigInteger.valueOf(sign*date.month):null,
+ null,
+ null,
+ null,
+ null);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/io/ASCIIReader.java b/resources/xerces2-j-src/org/apache/xerces/impl/io/ASCIIReader.java
new file mode 100644
index 0000000..6aa7ff5
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/io/ASCIIReader.java
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.Locale;
+
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.MessageFormatter;
+
+/**
+ * A simple ASCII byte reader. This is an optimized reader for reading
+ * byte streams that only contain 7-bit ASCII characters.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ *
+ * @version $Id$
+ */
+public final class ASCIIReader
+ extends Reader {
+
+ //
+ // Constants
+ //
+
+ /** Default byte buffer size (2048). */
+ public static final int DEFAULT_BUFFER_SIZE = 2048;
+
+ //
+ // Data
+ //
+
+ /** Input stream. */
+ protected final InputStream fInputStream;
+
+ /** Byte buffer. */
+ protected final byte[] fBuffer;
+
+ // message formatter; used to produce localized
+ // exception messages
+ private final MessageFormatter fFormatter;
+
+ //Locale to use for messages
+ private final Locale fLocale;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Constructs an ASCII reader from the specified input stream
+ * using the default buffer size.
+ *
+ * @param inputStream The input stream.
+ * @param messageFormatter the MessageFormatter to use to message reporting.
+ * @param locale the Locale for which messages are to be reported
+ */
+ public ASCIIReader(InputStream inputStream, MessageFormatter messageFormatter,
+ Locale locale) {
+ this(inputStream, DEFAULT_BUFFER_SIZE, messageFormatter, locale);
+ } // (InputStream, MessageFormatter, Locale)
+
+ /**
+ * Constructs an ASCII reader from the specified input stream
+ * and buffer size.
+ *
+ * @param inputStream The input stream.
+ * @param size The initial buffer size.
+ * @param messageFormatter the MessageFormatter to use to message reporting.
+ * @param locale the Locale for which messages are to be reported
+ */
+ public ASCIIReader(InputStream inputStream, int size,
+ MessageFormatter messageFormatter, Locale locale) {
+ this(inputStream, new byte[size], messageFormatter, locale);
+ } // (InputStream, int, MessageFormatter, Locale)
+
+ /**
+ * Constructs an ASCII reader from the specified input stream and buffer.
+ *
+ * @param inputStream The input stream.
+ * @param buffer The byte buffer.
+ * @param messageFormatter the MessageFormatter to use to message reporting.
+ * @param locale the Locale for which messages are to be reported
+ */
+ public ASCIIReader(InputStream inputStream, byte [] buffer,
+ MessageFormatter messageFormatter, Locale locale) {
+ fInputStream = inputStream;
+ fBuffer = buffer;
+ fFormatter = messageFormatter;
+ fLocale = locale;
+ } // (InputStream, byte[], MessageFormatter, Locale)
+
+ //
+ // Reader methods
+ //
+
+ /**
+ * Read a single character. This method will block until a character is
+ * available, an I/O error occurs, or the end of the stream is reached.
+ *
+ * Subclasses that intend to support efficient single-character input
+ * should override this method.
+ *
+ * @return The character read, as an integer in the range 0 to 127
+ * (0x00-0x7f), or -1 if the end of the stream has
+ * been reached
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public int read() throws IOException {
+ int b0 = fInputStream.read();
+ if (b0 >= 0x80) {
+ throw new MalformedByteSequenceException(fFormatter,
+ fLocale, XMLMessageFormatter.XML_DOMAIN,
+ "InvalidASCII", new Object [] {Integer.toString(b0)});
+ }
+ return b0;
+ } // read():int
+
+ /**
+ * Read characters into a portion of an array. This method will block
+ * until some input is available, an I/O error occurs, or the end of the
+ * stream is reached.
+ *
+ * @param ch Destination buffer
+ * @param offset Offset at which to start storing characters
+ * @param length Maximum number of characters to read
+ *
+ * @return The number of characters read, or -1 if the end of the
+ * stream has been reached
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public int read(char ch[], int offset, int length) throws IOException {
+ if (length > fBuffer.length) {
+ length = fBuffer.length;
+ }
+ int count = fInputStream.read(fBuffer, 0, length);
+ for (int i = 0; i < count; i++) {
+ int b0 = fBuffer[i];
+ if (b0 < 0) {
+ throw new MalformedByteSequenceException(fFormatter,
+ fLocale, XMLMessageFormatter.XML_DOMAIN,
+ "InvalidASCII", new Object [] {Integer.toString(b0 & 0x0FF)});
+ }
+ ch[offset + i] = (char)b0;
+ }
+ return count;
+ } // read(char[],int,int)
+
+ /**
+ * Skip characters. This method will block until some characters are
+ * available, an I/O error occurs, or the end of the stream is reached.
+ *
+ * @param n The number of characters to skip
+ *
+ * @return The number of characters actually skipped
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public long skip(long n) throws IOException {
+ return fInputStream.skip(n);
+ } // skip(long):long
+
+ /**
+ * Tell whether this stream is ready to be read.
+ *
+ * @return True if the next read() is guaranteed not to block for input,
+ * false otherwise. Note that returning false does not guarantee that the
+ * next read will block.
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public boolean ready() throws IOException {
+ return false;
+ } // ready()
+
+ /**
+ * Tell whether this stream supports the mark() operation.
+ */
+ public boolean markSupported() {
+ return fInputStream.markSupported();
+ } // markSupported()
+
+ /**
+ * Mark the present position in the stream. Subsequent calls to reset()
+ * will attempt to reposition the stream to this point. Not all
+ * character-input streams support the mark() operation.
+ *
+ * @param readAheadLimit Limit on the number of characters that may be
+ * read while still preserving the mark. After
+ * reading this many characters, attempting to
+ * reset the stream may fail.
+ *
+ * @exception IOException If the stream does not support mark(),
+ * or if some other I/O error occurs
+ */
+ public void mark(int readAheadLimit) throws IOException {
+ fInputStream.mark(readAheadLimit);
+ } // mark(int)
+
+ /**
+ * Reset the stream. If the stream has been marked, then attempt to
+ * reposition it at the mark. If the stream has not been marked, then
+ * attempt to reset it in some way appropriate to the particular stream,
+ * for example by repositioning it to its starting point. Not all
+ * character-input streams support the reset() operation, and some support
+ * reset() without supporting mark().
+ *
+ * @exception IOException If the stream has not been marked,
+ * or if the mark has been invalidated,
+ * or if the stream does not support reset(),
+ * or if some other I/O error occurs
+ */
+ public void reset() throws IOException {
+ fInputStream.reset();
+ } // reset()
+
+ /**
+ * Close the stream. Once a stream has been closed, further read(),
+ * ready(), mark(), or reset() invocations will throw an IOException.
+ * Closing a previously-closed stream, however, has no effect.
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public void close() throws IOException {
+ fInputStream.close();
+ } // close()
+
+} // class ASCIIReader
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/io/Latin1Reader.java b/resources/xerces2-j-src/org/apache/xerces/impl/io/Latin1Reader.java
new file mode 100644
index 0000000..2c94202
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/io/Latin1Reader.java
@@ -0,0 +1,214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * Reader for the ISO-8859-1 encoding.
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ *
+ * @version $Id$
+ */
+public final class Latin1Reader
+ extends Reader {
+
+ //
+ // Constants
+ //
+
+ /** Default byte buffer size (2048). */
+ public static final int DEFAULT_BUFFER_SIZE = 2048;
+
+ //
+ // Data
+ //
+
+ /** Input stream. */
+ protected final InputStream fInputStream;
+
+ /** Byte buffer. */
+ protected final byte[] fBuffer;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Constructs an ISO-8859-1 reader from the specified input stream
+ * using the default buffer size.
+ *
+ * @param inputStream The input stream.
+ */
+ public Latin1Reader(InputStream inputStream) {
+ this(inputStream, DEFAULT_BUFFER_SIZE);
+ } // (InputStream)
+
+ /**
+ * Constructs an ISO-8859-1 reader from the specified input stream
+ * and buffer size.
+ *
+ * @param inputStream The input stream.
+ * @param size The initial buffer size.
+ */
+ public Latin1Reader(InputStream inputStream, int size) {
+ this(inputStream, new byte[size]);
+ } // (InputStream, int)
+
+ /**
+ * Constructs an ISO-8859-1 reader from the specified input stream and buffer.
+ *
+ * @param inputStream The input stream.
+ * @param buffer The byte buffer.
+ */
+ public Latin1Reader(InputStream inputStream, byte [] buffer) {
+ fInputStream = inputStream;
+ fBuffer = buffer;
+ } // (InputStream, byte[])
+
+ //
+ // Reader methods
+ //
+
+ /**
+ * Read a single character. This method will block until a character is
+ * available, an I/O error occurs, or the end of the stream is reached.
+ *
+ * Subclasses that intend to support efficient single-character input
+ * should override this method.
+ *
+ * @return The character read, as an integer in the range 0 to 255
+ * (0x00-0xff), or -1 if the end of the stream has
+ * been reached
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public int read() throws IOException {
+ return fInputStream.read();
+ } // read():int
+
+ /**
+ * Read characters into a portion of an array. This method will block
+ * until some input is available, an I/O error occurs, or the end of the
+ * stream is reached.
+ *
+ * @param ch Destination buffer
+ * @param offset Offset at which to start storing characters
+ * @param length Maximum number of characters to read
+ *
+ * @return The number of characters read, or -1 if the end of the
+ * stream has been reached
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public int read(char ch[], int offset, int length) throws IOException {
+ if (length > fBuffer.length) {
+ length = fBuffer.length;
+ }
+ int count = fInputStream.read(fBuffer, 0, length);
+ for (int i = 0; i < count; ++i) {
+ ch[offset + i] = (char) (fBuffer[i] & 0xff);
+ }
+ return count;
+ } // read(char[],int,int)
+
+ /**
+ * Skip characters. This method will block until some characters are
+ * available, an I/O error occurs, or the end of the stream is reached.
+ *
+ * @param n The number of characters to skip
+ *
+ * @return The number of characters actually skipped
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public long skip(long n) throws IOException {
+ return fInputStream.skip(n);
+ } // skip(long):long
+
+ /**
+ * Tell whether this stream is ready to be read.
+ *
+ * @return True if the next read() is guaranteed not to block for input,
+ * false otherwise. Note that returning false does not guarantee that the
+ * next read will block.
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public boolean ready() throws IOException {
+ return false;
+ } // ready()
+
+ /**
+ * Tell whether this stream supports the mark() operation.
+ */
+ public boolean markSupported() {
+ return fInputStream.markSupported();
+ } // markSupported()
+
+ /**
+ * Mark the present position in the stream. Subsequent calls to reset()
+ * will attempt to reposition the stream to this point. Not all
+ * character-input streams support the mark() operation.
+ *
+ * @param readAheadLimit Limit on the number of characters that may be
+ * read while still preserving the mark. After
+ * reading this many characters, attempting to
+ * reset the stream may fail.
+ *
+ * @exception IOException If the stream does not support mark(),
+ * or if some other I/O error occurs
+ */
+ public void mark(int readAheadLimit) throws IOException {
+ fInputStream.mark(readAheadLimit);
+ } // mark(int)
+
+ /**
+ * Reset the stream. If the stream has been marked, then attempt to
+ * reposition it at the mark. If the stream has not been marked, then
+ * attempt to reset it in some way appropriate to the particular stream,
+ * for example by repositioning it to its starting point. Not all
+ * character-input streams support the reset() operation, and some support
+ * reset() without supporting mark().
+ *
+ * @exception IOException If the stream has not been marked,
+ * or if the mark has been invalidated,
+ * or if the stream does not support reset(),
+ * or if some other I/O error occurs
+ */
+ public void reset() throws IOException {
+ fInputStream.reset();
+ } // reset()
+
+ /**
+ * Close the stream. Once a stream has been closed, further read(),
+ * ready(), mark(), or reset() invocations will throw an IOException.
+ * Closing a previously-closed stream, however, has no effect.
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public void close() throws IOException {
+ fInputStream.close();
+ } // close()
+
+} // class Latin1Reader
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/io/MalformedByteSequenceException.java b/resources/xerces2-j-src/org/apache/xerces/impl/io/MalformedByteSequenceException.java
new file mode 100644
index 0000000..15a406b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/io/MalformedByteSequenceException.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.io;
+
+import java.io.CharConversionException;
+import java.util.Locale;
+
+import org.apache.xerces.util.MessageFormatter;
+
+/**
+ * Signals that a malformed byte sequence was detected
+ * by a java.io.Reader that decodes bytes
+ * of a given encoding into characters.
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ *
+ * @version $Id$
+ */
+public final class MalformedByteSequenceException extends CharConversionException {
+
+ /** Serialization version. */
+ static final long serialVersionUID = 8436382245048328739L;
+
+ //
+ // Data
+ //
+
+ /** message formatter **/
+ private MessageFormatter fFormatter;
+
+ /** locale for error message **/
+ private Locale fLocale;
+
+ /** error domain **/
+ private String fDomain;
+
+ /** key for the error message **/
+ private String fKey;
+
+ /** replacement arguements for the error message **/
+ private Object[] fArguments;
+
+ /** message text for this message, initially null **/
+ private String fMessage;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Constructs a MalformedByteSequenceException with the given
+ * parameters which may be passed to an error reporter to
+ * generate a localized string for this exception.
+ *
+ * @param formatter The MessageFormatter used for building the
+ * message text for this exception.
+ * @param locale The Locale for which messages are to be reported.
+ * @param domain The error domain.
+ * @param key The key of the error message.
+ * @param arguments The replacement arguments for the error message,
+ * if needed.
+ */
+ public MalformedByteSequenceException(MessageFormatter formatter,
+ Locale locale, String domain, String key, Object[] arguments) {
+ fFormatter = formatter;
+ fLocale = locale;
+ fDomain = domain;
+ fKey = key;
+ fArguments = arguments;
+ } // (MessageFormatter, Locale, String, String, Object[])
+
+ //
+ // Public methods
+ //
+
+ /**
+ * Returns the error domain of the error message.
+ *
+ * @return the error domain
+ */
+ public String getDomain () {
+ return fDomain;
+ } // getDomain
+
+ /**
+ * Returns the key of the error message.
+ *
+ * @return the error key of the error message
+ */
+ public String getKey () {
+ return fKey;
+ } // getKey()
+
+ /**
+ * Returns the replacement arguments for the error
+ * message or null if none exist.
+ *
+ * @return the replacement arguments for the error message
+ * or null if none exist
+ */
+ public Object[] getArguments () {
+ return fArguments;
+ } // getArguments();
+
+ /**
+ * Returns the localized message for this exception.
+ *
+ * @return the localized message for this exception.
+ */
+ public synchronized String getMessage() {
+ if (fMessage == null) {
+ fMessage = fFormatter.formatMessage(fLocale, fKey, fArguments);
+ // The references to the message formatter and locale
+ // aren't needed anymore so null them.
+ fFormatter = null;
+ fLocale = null;
+ }
+ return fMessage;
+ } // getMessage()
+
+} // MalformedByteSequenceException
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/io/UCSReader.java b/resources/xerces2-j-src/org/apache/xerces/impl/io/UCSReader.java
new file mode 100644
index 0000000..188387b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/io/UCSReader.java
@@ -0,0 +1,325 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * Reader for UCS-2 and UCS-4 encodings.
+ * (i.e., encodings from ISO-10646-UCS-(2|4)).
+ *
+ * @xerces.internal
+ *
+ * @author Neil Graham, IBM
+ *
+ * @version $Id$
+ */
+public final class UCSReader extends Reader {
+
+ //
+ // Constants
+ //
+
+ /**
+ * Default byte buffer size (8192, larger than that of ASCIIReader
+ * since it's reasonable to surmise that the average UCS-4-encoded
+ * file should be 4 times as large as the average ASCII-encoded file).
+ */
+ public static final int DEFAULT_BUFFER_SIZE = 8192;
+
+ public static final short UCS2LE = 1;
+ public static final short UCS2BE = 2;
+ public static final short UCS4LE = 4;
+ public static final short UCS4BE = 8;
+
+ //
+ // Data
+ //
+
+ /** Input stream. */
+ protected final InputStream fInputStream;
+
+ /** Byte buffer. */
+ protected final byte[] fBuffer;
+
+ // what kind of data we're dealing with
+ protected final short fEncoding;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Constructs a UCS reader from the specified input stream
+ * using the default buffer size. The Endian-ness and whether this is
+ * UCS-2 or UCS-4 needs also to be known in advance.
+ *
+ * @param inputStream The input stream.
+ * @param encoding One of UCS2LE, UCS2BE, UCS4LE or UCS4BE.
+ */
+ public UCSReader(InputStream inputStream, short encoding) {
+ this(inputStream, DEFAULT_BUFFER_SIZE, encoding);
+ } // (InputStream, short)
+
+ /**
+ * Constructs a UCS reader from the specified input stream
+ * and buffer size. The Endian-ness and whether this is
+ * UCS-2 or UCS-4 needs also to be known in advance.
+ *
+ * @param inputStream The input stream.
+ * @param size The initial buffer size.
+ * @param encoding One of UCS2LE, UCS2BE, UCS4LE or UCS4BE.
+ */
+ public UCSReader(InputStream inputStream, int size, short encoding) {
+ this(inputStream, new byte[size], encoding);
+ } // (InputStream,int,short)
+
+ /**
+ * Constructs a UCS reader from the specified input stream
+ * and buffer. The Endian-ness and whether this is
+ * UCS-2 or UCS-4 needs also to be known in advance.
+ *
+ * @param inputStream The input stream.
+ * @param buffer The byte buffer.
+ * @param encoding One of UCS2LE, UCS2BE, UCS4LE or UCS4BE.
+ */
+ public UCSReader(InputStream inputStream, byte [] buffer, short encoding) {
+ fInputStream = inputStream;
+ fBuffer = buffer;
+ fEncoding = encoding;
+ } // (InputStream,int,short)
+
+ //
+ // Reader methods
+ //
+
+ /**
+ * Read a single character. This method will block until a character is
+ * available, an I/O error occurs, or the end of the stream is reached.
+ *
+ * Subclasses that intend to support efficient single-character input
+ * should override this method.
+ *
+ * @return The character read, as an integer in the range 0 to 127
+ * (0x00-0x7f), or -1 if the end of the stream has
+ * been reached
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public int read() throws IOException {
+ int b0 = fInputStream.read() & 0xff;
+ if (b0 == 0xff) {
+ return -1;
+ }
+ int b1 = fInputStream.read() & 0xff;
+ if (b1 == 0xff) {
+ return -1;
+ }
+ // UCS-4
+ if (fEncoding >= 4) {
+ int b2 = fInputStream.read() & 0xff;
+ if (b2 == 0xff) {
+ return -1;
+ }
+ int b3 = fInputStream.read() & 0xff;
+ if (b3 == 0xff) {
+ return -1;
+ }
+ if (fEncoding == UCS4BE) {
+ return (b0<<24)+(b1<<16)+(b2<<8)+b3;
+ }
+ return (b3<<24)+(b2<<16)+(b1<<8)+b0;
+ }
+ // UCS-2
+ if (fEncoding == UCS2BE) {
+ return (b0<<8)+b1;
+ }
+ return (b1<<8)+b0;
+ } // read():int
+
+ /**
+ * Read characters into a portion of an array. This method will block
+ * until some input is available, an I/O error occurs, or the end of the
+ * stream is reached.
+ *
+ * @param ch Destination buffer
+ * @param offset Offset at which to start storing characters
+ * @param length Maximum number of characters to read
+ *
+ * @return The number of characters read, or -1 if the end of the
+ * stream has been reached
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public int read(char ch[], int offset, int length) throws IOException {
+ int byteLength = length << ((fEncoding >= 4)?2:1);
+ if (byteLength > fBuffer.length) {
+ byteLength = fBuffer.length;
+ }
+ int count = fInputStream.read(fBuffer, 0, byteLength);
+ if (count == -1) return -1;
+ // try and make count be a multiple of the number of bytes we're looking for
+ if (fEncoding >= 4) { // BigEndian
+ // this looks ugly, but it avoids an if at any rate...
+ int numToRead = (4 - (count & 3) & 3);
+ for (int i = 0; i < numToRead; i++) {
+ int charRead = fInputStream.read();
+ if (charRead == -1) { // end of input; something likely went wrong!A Pad buffer with nulls.
+ for (int j = i; j < numToRead; j++) {
+ fBuffer[count+j] = 0;
+ }
+ break;
+ }
+ fBuffer[count+i] = (byte)charRead;
+ }
+ count += numToRead;
+ }
+ else {
+ int numToRead = count & 1;
+ if (numToRead != 0) {
+ count++;
+ int charRead = fInputStream.read();
+ if (charRead == -1) { // end of input; something likely went wrong!A Pad buffer with nulls.
+ fBuffer[count] = 0;
+ }
+ else {
+ fBuffer[count] = (byte)charRead;
+ }
+ }
+ }
+
+ // now count is a multiple of the right number of bytes
+ int numChars = count >> ((fEncoding >= 4)?2:1);
+ int curPos = 0;
+ for (int i = 0; i < numChars; i++) {
+ int b0 = fBuffer[curPos++] & 0xff;
+ int b1 = fBuffer[curPos++] & 0xff;
+ // UCS-4
+ if (fEncoding >= 4) {
+ int b2 = fBuffer[curPos++] & 0xff;
+ int b3 = fBuffer[curPos++] & 0xff;
+ if (fEncoding == UCS4BE) {
+ ch[offset+i] = (char)((b0<<24)+(b1<<16)+(b2<<8)+b3);
+ }
+ else {
+ ch[offset+i] = (char)((b3<<24)+(b2<<16)+(b1<<8)+b0);
+ }
+ }
+ else { // UCS-2
+ if (fEncoding == UCS2BE) {
+ ch[offset+i] = (char)((b0<<8)+b1);
+ }
+ else {
+ ch[offset+i] = (char)((b1<<8)+b0);
+ }
+ }
+ }
+ return numChars;
+ } // read(char[],int,int)
+
+ /**
+ * Skip characters. This method will block until some characters are
+ * available, an I/O error occurs, or the end of the stream is reached.
+ *
+ * @param n The number of characters to skip
+ *
+ * @return The number of characters actually skipped
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public long skip(long n) throws IOException {
+ // charWidth will represent the number of bits to move
+ // n leftward to get num of bytes to skip, and then move the result rightward
+ // to get num of chars effectively skipped.
+ // The trick with &'ing, as with elsewhere in this dcode, is
+ // intended to avoid an expensive use of / that might not be optimized
+ // away.
+ int charWidth = (fEncoding >=4)?2:1;
+ long bytesSkipped = fInputStream.skip(n<> charWidth;
+ return (bytesSkipped >> charWidth) + 1;
+ } // skip(long):long
+
+ /**
+ * Tell whether this stream is ready to be read.
+ *
+ * @return True if the next read() is guaranteed not to block for input,
+ * false otherwise. Note that returning false does not guarantee that the
+ * next read will block.
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public boolean ready() throws IOException {
+ return false;
+ } // ready()
+
+ /**
+ * Tell whether this stream supports the mark() operation.
+ */
+ public boolean markSupported() {
+ return fInputStream.markSupported();
+ } // markSupported()
+
+ /**
+ * Mark the present position in the stream. Subsequent calls to reset()
+ * will attempt to reposition the stream to this point. Not all
+ * character-input streams support the mark() operation.
+ *
+ * @param readAheadLimit Limit on the number of characters that may be
+ * read while still preserving the mark. After
+ * reading this many characters, attempting to
+ * reset the stream may fail.
+ *
+ * @exception IOException If the stream does not support mark(),
+ * or if some other I/O error occurs
+ */
+ public void mark(int readAheadLimit) throws IOException {
+ fInputStream.mark(readAheadLimit);
+ } // mark(int)
+
+ /**
+ * Reset the stream. If the stream has been marked, then attempt to
+ * reposition it at the mark. If the stream has not been marked, then
+ * attempt to reset it in some way appropriate to the particular stream,
+ * for example by repositioning it to its starting point. Not all
+ * character-input streams support the reset() operation, and some support
+ * reset() without supporting mark().
+ *
+ * @exception IOException If the stream has not been marked,
+ * or if the mark has been invalidated,
+ * or if the stream does not support reset(),
+ * or if some other I/O error occurs
+ */
+ public void reset() throws IOException {
+ fInputStream.reset();
+ } // reset()
+
+ /**
+ * Close the stream. Once a stream has been closed, further read(),
+ * ready(), mark(), or reset() invocations will throw an IOException.
+ * Closing a previously-closed stream, however, has no effect.
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public void close() throws IOException {
+ fInputStream.close();
+ } // close()
+
+} // class UCSReader
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/io/UTF16Reader.java b/resources/xerces2-j-src/org/apache/xerces/impl/io/UTF16Reader.java
new file mode 100644
index 0000000..3318438
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/io/UTF16Reader.java
@@ -0,0 +1,323 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.Locale;
+
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.MessageFormatter;
+
+/**
+ * A UTF-16 reader. Can also be used for UCS-2 (i.e. ISO-10646-UCS-2).
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ *
+ * @version $Id$
+ */
+public final class UTF16Reader
+ extends Reader {
+
+ //
+ // Constants
+ //
+
+ /** Default byte buffer size (4096). */
+ public static final int DEFAULT_BUFFER_SIZE = 4096;
+
+ //
+ // Data
+ //
+
+ /** Input stream. */
+ protected final InputStream fInputStream;
+
+ /** Byte buffer. */
+ protected final byte[] fBuffer;
+
+ /** Endianness. */
+ protected final boolean fIsBigEndian;
+
+ // message formatter; used to produce localized exception messages
+ private final MessageFormatter fFormatter;
+
+ // Locale to use for messages
+ private final Locale fLocale;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Constructs a UTF-16 reader from the specified input stream
+ * using the default buffer size. Primarily for testing.
+ *
+ * @param inputStream The input stream.
+ * @param isBigEndian The byte order.
+ */
+ public UTF16Reader(InputStream inputStream, boolean isBigEndian) {
+ this(inputStream, DEFAULT_BUFFER_SIZE, isBigEndian,
+ new XMLMessageFormatter(), Locale.getDefault());
+ } // (InputStream, boolean)
+
+ /**
+ * Constructs a UTF-16 reader from the specified input stream
+ * using the default buffer size and the given MessageFormatter.
+ *
+ * @param inputStream The input stream.
+ * @param isBigEndian The byte order.
+ */
+ public UTF16Reader(InputStream inputStream, boolean isBigEndian,
+ MessageFormatter messageFormatter, Locale locale) {
+ this(inputStream, DEFAULT_BUFFER_SIZE, isBigEndian, messageFormatter, locale);
+ } // (InputStream, boolean, MessageFormatter, Locale)
+
+ /**
+ * Constructs a UTF-16 reader from the specified input stream
+ * and buffer size and given MessageFormatter.
+ *
+ * @param inputStream The input stream.
+ * @param size The initial buffer size.
+ * @param isBigEndian The byte order.
+ * @param messageFormatter Given MessageFormatter
+ * @param locale Locale to use for messages
+ */
+ public UTF16Reader(InputStream inputStream, int size, boolean isBigEndian,
+ MessageFormatter messageFormatter, Locale locale) {
+ this(inputStream, new byte[size], isBigEndian, messageFormatter, locale);
+ } // (InputStream, int, boolean, MessageFormatter, Locale)
+
+ /**
+ * Constructs a UTF-16 reader from the specified input stream,
+ * buffer and MessageFormatter.
+ *
+ * @param inputStream The input stream.
+ * @param buffer The byte buffer.
+ * @param isBigEndian The byte order.
+ * @param messageFormatter Given MessageFormatter
+ * @param locale Locale to use for messages
+ */
+ public UTF16Reader(InputStream inputStream, byte [] buffer, boolean isBigEndian,
+ MessageFormatter messageFormatter, Locale locale) {
+ fInputStream = inputStream;
+ fBuffer = buffer;
+ fIsBigEndian = isBigEndian;
+ fFormatter = messageFormatter;
+ fLocale = locale;
+ } // (InputStream, byte[], boolean, MessageFormatter, Locale)
+
+ //
+ // Reader methods
+ //
+
+ /**
+ * Read a single character. This method will block until a character is
+ * available, an I/O error occurs, or the end of the stream is reached.
+ *
+ * Subclasses that intend to support efficient single-character input
+ * should override this method.
+ *
+ * @return The character read, as an integer in the range 0 to 65535
+ * (0x00-0xffff), or -1 if the end of the stream has
+ * been reached
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public int read() throws IOException {
+ final int b0 = fInputStream.read();
+ if (b0 == -1) {
+ return -1;
+ }
+ final int b1 = fInputStream.read();
+ if (b1 == -1) {
+ expectedTwoBytes();
+ }
+ // UTF-16BE
+ if (fIsBigEndian) {
+ return (b0 << 8) | b1;
+ }
+ // UTF-16LE
+ return (b1 << 8) | b0;
+ } // read():int
+
+ /**
+ * Read characters into a portion of an array. This method will block
+ * until some input is available, an I/O error occurs, or the end of the
+ * stream is reached.
+ *
+ * @param ch Destination buffer
+ * @param offset Offset at which to start storing characters
+ * @param length Maximum number of characters to read
+ *
+ * @return The number of characters read, or -1 if the end of the
+ * stream has been reached
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public int read(char ch[], int offset, int length) throws IOException {
+ int byteLength = length << 1;
+ if (byteLength > fBuffer.length) {
+ byteLength = fBuffer.length;
+ }
+ int byteCount = fInputStream.read(fBuffer, 0, byteLength);
+ if (byteCount == -1) {
+ return -1;
+ }
+ // If an odd number of bytes were read, we still need to read one more.
+ if ((byteCount & 1) != 0) {
+ int b = fInputStream.read();
+ if (b == -1) {
+ expectedTwoBytes();
+ }
+ fBuffer[byteCount++] = (byte) b;
+ }
+ final int charCount = byteCount >> 1;
+ if (fIsBigEndian) {
+ processBE(ch, offset, charCount);
+ }
+ else {
+ processLE(ch, offset, charCount);
+ }
+ return charCount;
+ } // read(char[],int,int)
+
+ /**
+ * Skip characters. This method will block until some characters are
+ * available, an I/O error occurs, or the end of the stream is reached.
+ *
+ * @param n The number of characters to skip
+ *
+ * @return The number of characters actually skipped
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public long skip(long n) throws IOException {
+ long bytesSkipped = fInputStream.skip(n << 1);
+ if ((bytesSkipped & 1) != 0) {
+ int b = fInputStream.read();
+ if (b == -1) {
+ expectedTwoBytes();
+ }
+ ++bytesSkipped;
+ }
+ return bytesSkipped >> 1;
+ } // skip(long):long
+
+ /**
+ * Tell whether this stream is ready to be read.
+ *
+ * @return True if the next read() is guaranteed not to block for input,
+ * false otherwise. Note that returning false does not guarantee that the
+ * next read will block.
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public boolean ready() throws IOException {
+ return false;
+ } // ready()
+
+ /**
+ * Tell whether this stream supports the mark() operation.
+ */
+ public boolean markSupported() {
+ return false;
+ } // markSupported()
+
+ /**
+ * Mark the present position in the stream. Subsequent calls to reset()
+ * will attempt to reposition the stream to this point. Not all
+ * character-input streams support the mark() operation.
+ *
+ * @param readAheadLimit Limit on the number of characters that may be
+ * read while still preserving the mark. After
+ * reading this many characters, attempting to
+ * reset the stream may fail.
+ *
+ * @exception IOException If the stream does not support mark(),
+ * or if some other I/O error occurs
+ */
+ public void mark(int readAheadLimit) throws IOException {
+ throw new IOException(fFormatter.formatMessage(fLocale, "OperationNotSupported", new Object[]{"mark()", "UTF-16"}));
+ } // mark(int)
+
+ /**
+ * Reset the stream. If the stream has been marked, then attempt to
+ * reposition it at the mark. If the stream has not been marked, then
+ * attempt to reset it in some way appropriate to the particular stream,
+ * for example by repositioning it to its starting point. Not all
+ * character-input streams support the reset() operation, and some support
+ * reset() without supporting mark().
+ *
+ * @exception IOException If the stream has not been marked,
+ * or if the mark has been invalidated,
+ * or if the stream does not support reset(),
+ * or if some other I/O error occurs
+ */
+ public void reset() throws IOException {
+ } // reset()
+
+ /**
+ * Close the stream. Once a stream has been closed, further read(),
+ * ready(), mark(), or reset() invocations will throw an IOException.
+ * Closing a previously-closed stream, however, has no effect.
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public void close() throws IOException {
+ fInputStream.close();
+ } // close()
+
+ //
+ // Private methods
+ //
+
+ /** Decodes UTF-16BE **/
+ private void processBE(final char ch[], int offset, final int count) {
+ int curPos = 0;
+ for (int i = 0; i < count; ++i) {
+ final int b0 = fBuffer[curPos++] & 0xff;
+ final int b1 = fBuffer[curPos++] & 0xff;
+ ch[offset++] = (char) ((b0 << 8) | b1);
+ }
+ } // processBE(char[],int,int)
+
+ /** Decodes UTF-16LE **/
+ private void processLE(final char ch[], int offset, final int count) {
+ int curPos = 0;
+ for (int i = 0; i < count; ++i) {
+ final int b0 = fBuffer[curPos++] & 0xff;
+ final int b1 = fBuffer[curPos++] & 0xff;
+ ch[offset++] = (char) ((b1 << 8) | b0);
+ }
+ } // processLE(char[],int,int)
+
+ /** Throws an exception for expected byte. */
+ private void expectedTwoBytes()
+ throws MalformedByteSequenceException {
+ throw new MalformedByteSequenceException(fFormatter,
+ fLocale,
+ XMLMessageFormatter.XML_DOMAIN,
+ "ExpectedByte",
+ new Object[] {"2", "2"});
+ } // expectedTwoBytes()
+
+} // class UTF16Reader
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/io/UTF8Reader.java b/resources/xerces2-j-src/org/apache/xerces/impl/io/UTF8Reader.java
new file mode 100644
index 0000000..dc46e7a
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/io/UTF8Reader.java
@@ -0,0 +1,713 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.Locale;
+
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.util.MessageFormatter;
+
+/**
+ * A UTF-8 reader.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ *
+ * @version $Id$
+ */
+public final class UTF8Reader
+ extends Reader {
+
+ //
+ // Constants
+ //
+
+ /** Default byte buffer size (2048). */
+ public static final int DEFAULT_BUFFER_SIZE = 2048;
+
+ // debugging
+
+ /** Debug read. */
+ private static final boolean DEBUG_READ = false;
+
+ //
+ // Data
+ //
+
+ /** Input stream. */
+ protected final InputStream fInputStream;
+
+ /** Byte buffer. */
+ protected final byte[] fBuffer;
+
+ /** Offset into buffer. */
+ protected int fOffset;
+
+ /** Surrogate character. */
+ private int fSurrogate = -1;
+
+ // message formatter; used to produce localized
+ // exception messages
+ private final MessageFormatter fFormatter;
+
+ //Locale to use for messages
+ private final Locale fLocale;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Constructs a UTF-8 reader from the specified input stream
+ * using the default buffer size. Primarily for testing.
+ *
+ * @param inputStream The input stream.
+ */
+ public UTF8Reader(InputStream inputStream) {
+ this(inputStream, DEFAULT_BUFFER_SIZE, new XMLMessageFormatter(), Locale.getDefault());
+ } // (InputStream, MessageFormatter)
+
+ /**
+ * Constructs a UTF-8 reader from the specified input stream
+ * using the default buffer size and the given MessageFormatter.
+ *
+ * @param inputStream The input stream.
+ * @param messageFormatter given MessageFormatter
+ * @param locale Locale to use for messages
+ */
+ public UTF8Reader(InputStream inputStream, MessageFormatter messageFormatter,
+ Locale locale) {
+ this(inputStream, DEFAULT_BUFFER_SIZE, messageFormatter, locale);
+ } // (InputStream, MessageFormatter, Locale)
+
+ /**
+ * Constructs a UTF-8 reader from the specified input stream,
+ * buffer size and MessageFormatter.
+ *
+ * @param inputStream The input stream.
+ * @param size The initial buffer size.
+ * @param messageFormatter the formatter for localizing/formatting errors.
+ * @param locale the Locale to use for messages
+ */
+ public UTF8Reader(InputStream inputStream, int size,
+ MessageFormatter messageFormatter, Locale locale) {
+ this(inputStream, new byte[size], messageFormatter, locale);
+ } // (InputStream, int, MessageFormatter, Locale)
+
+ /**
+ * Constructs a UTF-8 reader from the specified input stream,
+ * buffer and MessageFormatter.
+ *
+ * @param inputStream The input stream.
+ * @param buffer The byte buffer.
+ * @param messageFormatter the formatter for localizing/formatting errors.
+ * @param locale the Locale to use for messages
+ */
+ public UTF8Reader(InputStream inputStream, byte [] buffer,
+ MessageFormatter messageFormatter, Locale locale) {
+ fInputStream = inputStream;
+ fBuffer = buffer;
+ fFormatter = messageFormatter;
+ fLocale = locale;
+ } // (InputStream, byte[], MessageFormatter, Locale)
+
+ //
+ // Reader methods
+ //
+
+ /**
+ * Read a single character. This method will block until a character is
+ * available, an I/O error occurs, or the end of the stream is reached.
+ *
+ * Subclasses that intend to support efficient single-character input
+ * should override this method.
+ *
+ * @return The character read, as an integer in the range 0 to 16383
+ * (0x00-0xffff), or -1 if the end of the stream has
+ * been reached
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public int read() throws IOException {
+
+ // decode character
+ int c = fSurrogate;
+ if (fSurrogate == -1) {
+ // NOTE: We use the index into the buffer if there are remaining
+ // bytes from the last block read. -Ac
+ int index = 0;
+
+ // get first byte
+ int b0 = index == fOffset
+ ? fInputStream.read() : fBuffer[index++] & 0x00FF;
+ if (b0 == -1) {
+ return -1;
+ }
+
+ // UTF-8: [0xxx xxxx]
+ // Unicode: [0000 0000] [0xxx xxxx]
+ if (b0 < 0x80) {
+ c = (char)b0;
+ }
+
+ // UTF-8: [110y yyyy] [10xx xxxx]
+ // Unicode: [0000 0yyy] [yyxx xxxx]
+ else if ((b0 & 0xE0) == 0xC0 && (b0 & 0x1E) != 0) {
+ int b1 = index == fOffset
+ ? fInputStream.read() : fBuffer[index++] & 0x00FF;
+ if (b1 == -1) {
+ expectedByte(2, 2);
+ }
+ if ((b1 & 0xC0) != 0x80) {
+ invalidByte(2, 2, b1);
+ }
+ c = ((b0 << 6) & 0x07C0) | (b1 & 0x003F);
+ }
+
+ // UTF-8: [1110 zzzz] [10yy yyyy] [10xx xxxx]
+ // Unicode: [zzzz yyyy] [yyxx xxxx]
+ else if ((b0 & 0xF0) == 0xE0) {
+ int b1 = index == fOffset
+ ? fInputStream.read() : fBuffer[index++] & 0x00FF;
+ if (b1 == -1) {
+ expectedByte(2, 3);
+ }
+ if ((b1 & 0xC0) != 0x80
+ || (b0 == 0xED && b1 >= 0xA0)
+ || ((b0 & 0x0F) == 0 && (b1 & 0x20) == 0)) {
+ invalidByte(2, 3, b1);
+ }
+ int b2 = index == fOffset
+ ? fInputStream.read() : fBuffer[index++] & 0x00FF;
+ if (b2 == -1) {
+ expectedByte(3, 3);
+ }
+ if ((b2 & 0xC0) != 0x80) {
+ invalidByte(3, 3, b2);
+ }
+ c = ((b0 << 12) & 0xF000) | ((b1 << 6) & 0x0FC0) |
+ (b2 & 0x003F);
+ }
+
+ // UTF-8: [1111 0uuu] [10uu zzzz] [10yy yyyy] [10xx xxxx]*
+ // Unicode: [1101 10ww] [wwzz zzyy] (high surrogate)
+ // [1101 11yy] [yyxx xxxx] (low surrogate)
+ // * uuuuu = wwww + 1
+ else if ((b0 & 0xF8) == 0xF0) {
+ int b1 = index == fOffset
+ ? fInputStream.read() : fBuffer[index++] & 0x00FF;
+ if (b1 == -1) {
+ expectedByte(2, 4);
+ }
+ if ((b1 & 0xC0) != 0x80
+ || ((b1 & 0x30) == 0 && (b0 & 0x07) == 0)) {
+ invalidByte(2, 3, b1);
+ }
+ int b2 = index == fOffset
+ ? fInputStream.read() : fBuffer[index++] & 0x00FF;
+ if (b2 == -1) {
+ expectedByte(3, 4);
+ }
+ if ((b2 & 0xC0) != 0x80) {
+ invalidByte(3, 3, b2);
+ }
+ int b3 = index == fOffset
+ ? fInputStream.read() : fBuffer[index++] & 0x00FF;
+ if (b3 == -1) {
+ expectedByte(4, 4);
+ }
+ if ((b3 & 0xC0) != 0x80) {
+ invalidByte(4, 4, b3);
+ }
+ int uuuuu = ((b0 << 2) & 0x001C) | ((b1 >> 4) & 0x0003);
+ if (uuuuu > 0x10) {
+ invalidSurrogate(uuuuu);
+ }
+ int wwww = uuuuu - 1;
+ int hs = 0xD800 |
+ ((wwww << 6) & 0x03C0) | ((b1 << 2) & 0x003C) |
+ ((b2 >> 4) & 0x0003);
+ int ls = 0xDC00 | ((b2 << 6) & 0x03C0) | (b3 & 0x003F);
+ c = hs;
+ fSurrogate = ls;
+ }
+
+ // error
+ else {
+ invalidByte(1, 1, b0);
+ }
+ }
+
+ // use surrogate
+ else {
+ fSurrogate = -1;
+ }
+
+ // return character
+ if (DEBUG_READ) {
+ System.out.println("read(): 0x"+Integer.toHexString(c));
+ }
+ return c;
+
+ } // read():int
+
+ /**
+ * Read characters into a portion of an array. This method will block
+ * until some input is available, an I/O error occurs, or the end of the
+ * stream is reached.
+ *
+ * @param ch Destination buffer
+ * @param offset Offset at which to start storing characters
+ * @param length Maximum number of characters to read
+ *
+ * @return The number of characters read, or -1 if the end of the
+ * stream has been reached
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public int read(char ch[], int offset, int length) throws IOException {
+
+ // read bytes
+ int out = offset;
+ int count = 0;
+ if (fOffset == 0) {
+ // adjust length to read
+ if (length > fBuffer.length) {
+ length = fBuffer.length;
+ }
+
+ // handle surrogate
+ if (fSurrogate != -1) {
+ ch[out++] = (char)fSurrogate;
+ fSurrogate = -1;
+ length--;
+ }
+
+ // perform read operation
+ count = fInputStream.read(fBuffer, 0, length);
+ if (count == -1) {
+ return -1;
+ }
+ count += out - offset;
+ }
+
+ // skip read; last character was in error
+ // NOTE: Having an offset value other than zero means that there was
+ // an error in the last character read. In this case, we have
+ // skipped the read so we don't consume any bytes past the
+ // error. By signalling the error on the next block read we
+ // allow the method to return the most valid characters that
+ // it can on the previous block read. -Ac
+ else {
+ count = fOffset;
+ fOffset = 0;
+ }
+
+ // convert bytes to characters
+ final int total = count;
+ int in;
+ byte byte1;
+ final byte byte0 = 0;
+ for (in = 0; in < total; in++) {
+ byte1 = fBuffer[in];
+ if (byte1 >= byte0) {
+ ch[out++] = (char)byte1;
+ }
+ else {
+ break;
+ }
+ }
+ for ( ; in < total; in++) {
+ byte1 = fBuffer[in];
+
+ // UTF-8: [0xxx xxxx]
+ // Unicode: [0000 0000] [0xxx xxxx]
+ if (byte1 >= byte0) {
+ ch[out++] = (char)byte1;
+ continue;
+ }
+
+ // UTF-8: [110y yyyy] [10xx xxxx]
+ // Unicode: [0000 0yyy] [yyxx xxxx]
+ int b0 = byte1 & 0x0FF;
+ if ((b0 & 0xE0) == 0xC0 && (b0 & 0x1E) != 0) {
+ int b1 = -1;
+ if (++in < total) {
+ b1 = fBuffer[in] & 0x00FF;
+ }
+ else {
+ b1 = fInputStream.read();
+ if (b1 == -1) {
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fOffset = 1;
+ return out - offset;
+ }
+ expectedByte(2, 2);
+ }
+ count++;
+ }
+ if ((b1 & 0xC0) != 0x80) {
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fBuffer[1] = (byte)b1;
+ fOffset = 2;
+ return out - offset;
+ }
+ invalidByte(2, 2, b1);
+ }
+ int c = ((b0 << 6) & 0x07C0) | (b1 & 0x003F);
+ ch[out++] = (char)c;
+ count -= 1;
+ continue;
+ }
+
+ // UTF-8: [1110 zzzz] [10yy yyyy] [10xx xxxx]
+ // Unicode: [zzzz yyyy] [yyxx xxxx]
+ if ((b0 & 0xF0) == 0xE0) {
+ int b1 = -1;
+ if (++in < total) {
+ b1 = fBuffer[in] & 0x00FF;
+ }
+ else {
+ b1 = fInputStream.read();
+ if (b1 == -1) {
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fOffset = 1;
+ return out - offset;
+ }
+ expectedByte(2, 3);
+ }
+ count++;
+ }
+ if ((b1 & 0xC0) != 0x80
+ || (b0 == 0xED && b1 >= 0xA0)
+ || ((b0 & 0x0F) == 0 && (b1 & 0x20) == 0)) {
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fBuffer[1] = (byte)b1;
+ fOffset = 2;
+ return out - offset;
+ }
+ invalidByte(2, 3, b1);
+ }
+ int b2 = -1;
+ if (++in < total) {
+ b2 = fBuffer[in] & 0x00FF;
+ }
+ else {
+ b2 = fInputStream.read();
+ if (b2 == -1) {
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fBuffer[1] = (byte)b1;
+ fOffset = 2;
+ return out - offset;
+ }
+ expectedByte(3, 3);
+ }
+ count++;
+ }
+ if ((b2 & 0xC0) != 0x80) {
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fBuffer[1] = (byte)b1;
+ fBuffer[2] = (byte)b2;
+ fOffset = 3;
+ return out - offset;
+ }
+ invalidByte(3, 3, b2);
+ }
+ int c = ((b0 << 12) & 0xF000) | ((b1 << 6) & 0x0FC0) |
+ (b2 & 0x003F);
+ ch[out++] = (char)c;
+ count -= 2;
+ continue;
+ }
+
+ // UTF-8: [1111 0uuu] [10uu zzzz] [10yy yyyy] [10xx xxxx]*
+ // Unicode: [1101 10ww] [wwzz zzyy] (high surrogate)
+ // [1101 11yy] [yyxx xxxx] (low surrogate)
+ // * uuuuu = wwww + 1
+ if ((b0 & 0xF8) == 0xF0) {
+ int b1 = -1;
+ if (++in < total) {
+ b1 = fBuffer[in] & 0x00FF;
+ }
+ else {
+ b1 = fInputStream.read();
+ if (b1 == -1) {
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fOffset = 1;
+ return out - offset;
+ }
+ expectedByte(2, 4);
+ }
+ count++;
+ }
+ if ((b1 & 0xC0) != 0x80
+ || ((b1 & 0x30) == 0 && (b0 & 0x07) == 0)) {
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fBuffer[1] = (byte)b1;
+ fOffset = 2;
+ return out - offset;
+ }
+ invalidByte(2, 4, b1);
+ }
+ int b2 = -1;
+ if (++in < total) {
+ b2 = fBuffer[in] & 0x00FF;
+ }
+ else {
+ b2 = fInputStream.read();
+ if (b2 == -1) {
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fBuffer[1] = (byte)b1;
+ fOffset = 2;
+ return out - offset;
+ }
+ expectedByte(3, 4);
+ }
+ count++;
+ }
+ if ((b2 & 0xC0) != 0x80) {
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fBuffer[1] = (byte)b1;
+ fBuffer[2] = (byte)b2;
+ fOffset = 3;
+ return out - offset;
+ }
+ invalidByte(3, 4, b2);
+ }
+ int b3 = -1;
+ if (++in < total) {
+ b3 = fBuffer[in] & 0x00FF;
+ }
+ else {
+ b3 = fInputStream.read();
+ if (b3 == -1) {
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fBuffer[1] = (byte)b1;
+ fBuffer[2] = (byte)b2;
+ fOffset = 3;
+ return out - offset;
+ }
+ expectedByte(4, 4);
+ }
+ count++;
+ }
+ if ((b3 & 0xC0) != 0x80) {
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fBuffer[1] = (byte)b1;
+ fBuffer[2] = (byte)b2;
+ fBuffer[3] = (byte)b3;
+ fOffset = 4;
+ return out - offset;
+ }
+ invalidByte(4, 4, b2);
+ }
+
+ // decode bytes into surrogate characters
+ int uuuuu = ((b0 << 2) & 0x001C) | ((b1 >> 4) & 0x0003);
+ if (uuuuu > 0x10) {
+ invalidSurrogate(uuuuu);
+ }
+ int wwww = uuuuu - 1;
+ int zzzz = b1 & 0x000F;
+ int yyyyyy = b2 & 0x003F;
+ int xxxxxx = b3 & 0x003F;
+ int hs = 0xD800 | ((wwww << 6) & 0x03C0) | (zzzz << 2) | (yyyyyy >> 4);
+ int ls = 0xDC00 | ((yyyyyy << 6) & 0x03C0) | xxxxxx;
+
+ // set characters
+ ch[out++] = (char)hs;
+ if ((count -= 2) <= length) {
+ ch[out++] = (char)ls;
+ }
+ // reached the end of the char buffer; save low surrogate for the next read
+ else {
+ fSurrogate = ls;
+ --count;
+ }
+ continue;
+ }
+
+ // error
+ if (out > offset) {
+ fBuffer[0] = (byte)b0;
+ fOffset = 1;
+ return out - offset;
+ }
+ invalidByte(1, 1, b0);
+ }
+
+ // return number of characters converted
+ if (DEBUG_READ) {
+ System.out.println("read(char[],"+offset+','+length+"): count="+count);
+ }
+ return count;
+
+ } // read(char[],int,int)
+
+ /**
+ * Skip characters. This method will block until some characters are
+ * available, an I/O error occurs, or the end of the stream is reached.
+ *
+ * @param n The number of characters to skip
+ *
+ * @return The number of characters actually skipped
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public long skip(long n) throws IOException {
+
+ long remaining = n;
+ final char[] ch = new char[fBuffer.length];
+ do {
+ int length = ch.length < remaining ? ch.length : (int)remaining;
+ int count = read(ch, 0, length);
+ if (count > 0) {
+ remaining -= count;
+ }
+ else {
+ break;
+ }
+ } while (remaining > 0);
+
+ long skipped = n - remaining;
+ return skipped;
+
+ } // skip(long):long
+
+ /**
+ * Tell whether this stream is ready to be read.
+ *
+ * @return True if the next read() is guaranteed not to block for input,
+ * false otherwise. Note that returning false does not guarantee that the
+ * next read will block.
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public boolean ready() throws IOException {
+ return false;
+ } // ready()
+
+ /**
+ * Tell whether this stream supports the mark() operation.
+ */
+ public boolean markSupported() {
+ return false;
+ } // markSupported()
+
+ /**
+ * Mark the present position in the stream. Subsequent calls to reset()
+ * will attempt to reposition the stream to this point. Not all
+ * character-input streams support the mark() operation.
+ *
+ * @param readAheadLimit Limit on the number of characters that may be
+ * read while still preserving the mark. After
+ * reading this many characters, attempting to
+ * reset the stream may fail.
+ *
+ * @exception IOException If the stream does not support mark(),
+ * or if some other I/O error occurs
+ */
+ public void mark(int readAheadLimit) throws IOException {
+ throw new IOException(fFormatter.formatMessage(fLocale, "OperationNotSupported", new Object[]{"mark()", "UTF-8"}));
+ } // mark(int)
+
+ /**
+ * Reset the stream. If the stream has been marked, then attempt to
+ * reposition it at the mark. If the stream has not been marked, then
+ * attempt to reset it in some way appropriate to the particular stream,
+ * for example by repositioning it to its starting point. Not all
+ * character-input streams support the reset() operation, and some support
+ * reset() without supporting mark().
+ *
+ * @exception IOException If the stream has not been marked,
+ * or if the mark has been invalidated,
+ * or if the stream does not support reset(),
+ * or if some other I/O error occurs
+ */
+ public void reset() throws IOException {
+ fOffset = 0;
+ fSurrogate = -1;
+ } // reset()
+
+ /**
+ * Close the stream. Once a stream has been closed, further read(),
+ * ready(), mark(), or reset() invocations will throw an IOException.
+ * Closing a previously-closed stream, however, has no effect.
+ *
+ * @exception IOException If an I/O error occurs
+ */
+ public void close() throws IOException {
+ fInputStream.close();
+ } // close()
+
+ //
+ // Private methods
+ //
+
+ /** Throws an exception for expected byte. */
+ private void expectedByte(int position, int count)
+ throws MalformedByteSequenceException {
+
+ throw new MalformedByteSequenceException(fFormatter,
+ fLocale,
+ XMLMessageFormatter.XML_DOMAIN,
+ "ExpectedByte",
+ new Object[] {Integer.toString(position), Integer.toString(count)});
+
+ } // expectedByte(int,int)
+
+ /** Throws an exception for invalid byte. */
+ private void invalidByte(int position, int count, int c)
+ throws MalformedByteSequenceException {
+
+ throw new MalformedByteSequenceException(fFormatter,
+ fLocale,
+ XMLMessageFormatter.XML_DOMAIN,
+ "InvalidByte",
+ new Object [] {Integer.toString(position), Integer.toString(count)});
+
+ } // invalidByte(int,int,int)
+
+ /** Throws an exception for invalid surrogate bits. */
+ private void invalidSurrogate(int uuuuu) throws MalformedByteSequenceException {
+
+ throw new MalformedByteSequenceException(fFormatter,
+ fLocale,
+ XMLMessageFormatter.XML_DOMAIN,
+ "InvalidHighSurrogate",
+ new Object[] {Integer.toHexString(uuuuu)});
+
+ } // invalidSurrogate(int)
+
+} // class UTF8Reader
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/msg/DOMMessages.properties b/resources/xerces2-j-src/org/apache/xerces/impl/msg/DOMMessages.properties
new file mode 100644
index 0000000..7ad6e8d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/msg/DOMMessages.properties
@@ -0,0 +1,83 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces
+# DOM implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id$
+
+ BadMessageKey = The error message corresponding to the message key can not be found.
+ FormatFailed = An internal error occurred while formatting the following message:\n
+
+# DOM Core
+
+# exception codes
+DOMSTRING_SIZE_ERR = The specified range of text does not fit into a DOMString.
+HIERARCHY_REQUEST_ERR = An attempt was made to insert a node where it is not permitted.
+INDEX_SIZE_ERR = The index or size is negative, or greater than the allowed value.
+INUSE_ATTRIBUTE_ERR = An attempt is made to add an attribute that is already in use elsewhere.
+INVALID_ACCESS_ERR = A parameter or an operation is not supported by the underlying object.
+INVALID_CHARACTER_ERR = An invalid or illegal XML character is specified.
+INVALID_MODIFICATION_ERR = An attempt is made to modify the type of the underlying object.
+INVALID_STATE_ERR = An attempt is made to use an object that is not, or is no longer, usable.
+NAMESPACE_ERR = An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
+NOT_FOUND_ERR = An attempt is made to reference a node in a context where it does not exist.
+NOT_SUPPORTED_ERR = The implementation does not support the requested type of object or operation.
+NO_DATA_ALLOWED_ERR = Data is specified for a node which does not support data.
+NO_MODIFICATION_ALLOWED_ERR = An attempt is made to modify an object where modifications are not allowed.
+SYNTAX_ERR = An invalid or illegal string is specified.
+VALIDATION_ERR = A call to a method such as insertBefore or removeChild would make the Node invalid with respect to document grammar.
+WRONG_DOCUMENT_ERR = A node is used in a different document than the one that created it.
+TYPE_MISMATCH_ERR = The value type for this parameter name is incompatible with the expected value type.
+
+#error messages or exceptions
+FEATURE_NOT_SUPPORTED = The parameter {0} is recognized but the requested value cannot be set.
+FEATURE_NOT_FOUND = The parameter {0} is not recognized.
+STRING_TOO_LONG = The resulting string is too long to fit in a DOMString: ''{0}''.
+
+#DOM Level 3 DOMError codes
+wf-invalid-character = The text {0} of the {1} node contains invalid XML characters.
+wf-invalid-character-in-node-name = The {0} node named {1} contains invalid XML characters.
+cdata-sections-splitted = CDATA sections containing the CDATA section termination marker \"]]>\"
+doctype-not-allowed = DOCTYPE declaration is not allowed.
+unsupported-encoding = The encoding {0} is not supported.
+
+#Error codes used in DOM Normalizer
+InvalidXMLCharInDOM = An invalid XML character (Unicode: 0x{0}) was found in the DOM during normalization.
+UndeclaredEntRefInAttrValue = The attribute \"{0}\" value \"{1}\" referenced an entity that was not declared.
+NullLocalElementName = A null local name was encountered during namespace normalization of element {0}.
+NullLocalAttrName = A null local name was encountered during namespace normalization of attribute {0}.
+
+#Error codes used in DOMParser
+InvalidDocumentClassName = The class name of the document factory \"{0}\" used to construct the DOM tree is not of type org.w3c.dom.Document.
+MissingDocumentClassName = The class name of the document factory \"{0}\" used to construct the DOM tree could not be found.
+CannotCreateDocumentClass = The class named \"{0}\" could not be constructed as a org.w3c.dom.Document.
+CannotQueryDeferredNode = Current element node cannot be queried when node expansion is deferred.
+
+# Error codes used by JAXP DocumentBuilder
+jaxp-order-not-supported = Property ''{0}'' must be set before setting property ''{1}''.
+jaxp-null-input-source = The source specified cannot be null.
+
+#Ranges
+BAD_BOUNDARYPOINTS_ERR = The boundary-points of a Range do not meet specific requirements.
+INVALID_NODE_TYPE_ERR = The container of a boundary-point of a Range is being set to either a node of an invalid type or a node with an ancestor of an invalid type.
+
+#Events
+UNSPECIFIED_EVENT_TYPE_ERR = The Event's type was not specified by initializing the event before the method was called.
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/msg/DatatypeMessages.properties b/resources/xerces2-j-src/org/apache/xerces/impl/msg/DatatypeMessages.properties
new file mode 100644
index 0000000..4743d56
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/msg/DatatypeMessages.properties
@@ -0,0 +1,47 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces JAXP Datatype API implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id$
+
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n
+
+FieldCannotBeNull={0} cannot be called with 'null' parameter.
+UnknownField={0} called with an unknown field\:{1}
+#There are two similar keys 'InvalidXMLGreogorianCalendarValue' . Suffix (year, month) has been added and are used as per the context.
+InvalidXGCValue-milli=Year \= {0}, Month \= {1}, Day \= {2}, Hour \= {3}, Minute \= {4}, Second \= {5}, fractionalSecond \= {6}, Timezone \= {7} , is not a valid representation of an XML Gregorian Calendar value.
+#There are two similar keys 'InvalidXMLGreogorianCalendarValue' . Suffix (year, month) has been added and are used as per the context.
+InvalidXGCValue-fractional=Year \= {0}, Month \= {1}, Day \= {2}, Hour \= {3}, Minute \= {4}, Second \= {5}, fractionalSecond \= {6}, Timezone \= {7} , is not a valid representation of an XML Gregorian Calendar value.
+
+InvalidXGCFields=Invalid set of fields set for XMLGregorianCalendar
+
+InvalidFractional=Invalid value {0} for fractional second.
+
+#XGC stands for XML Gregorian Calendar
+InvalidXGCRepresentation="{0}" is not a valid representation of an XML Gregorian Calendar value.
+
+InvalidFieldValue=Invalid value {0} for {1} field.
+
+NegativeField= {0} field is negative
+
+AllFieldsNull=All the fields (javax.xml.datatype.DatatypeConstants.Field) are null.
+
+TooLarge={0} value "{1}" too large to be supported by this implementation
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/msg/JAXPValidationMessages.properties b/resources/xerces2-j-src/org/apache/xerces/impl/msg/JAXPValidationMessages.properties
new file mode 100644
index 0000000..0725796
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/msg/JAXPValidationMessages.properties
@@ -0,0 +1,50 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces JAXP Validation API implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id$
+
+# Messages for message reporting
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n
+
+# SchemaFactory error messages
+SchemaLanguageNull = The schema language specified cannot be null.
+SchemaLanguageLengthZero = The schema language specified cannot have a length of zero characters.
+SchemaSourceArrayNull = The Source array parameter cannot be null.
+SchemaSourceArrayMemberNull = The Source array parameter cannot contain any items that are null.
+SchemaFactorySourceUnrecognized = Source parameter of type ''{0}'' is not recognized by this SchemaFactory.
+SAXSourceNullInputSource = The SAXSource specified contains no InputSource.
+
+# Validator error messages
+SourceParameterNull = Source parameter cannot be null.
+SourceNotAccepted = Source parameter of type ''{0}'' is not accepted by this validator.
+SourceResultMismatch = Source parameter of type ''{0}'' is not compatible with result parameter of type ''{1}''.
+StAXIllegalInitialState = Expecting the initial state to be start document or start element.
+StreamResultNotInitialized = The StreamResult contains no OutputStream, Writer, or system ID.
+
+# TypeInfoProvider error messages
+TypeInfoProviderIllegalStateElement = Element type information cannot be queried from a TypeInfoProvider outside of a startElement or endElement callback.
+TypeInfoProviderIllegalStateAttribute = Attribute type information cannot be queried from a TypeInfoProvider outside of a startElement callback.
+
+# General error messages
+FeatureNameNull = The feature name cannot be null.
+ProperyNameNull = The property name cannot be null.
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/msg/SAXMessages.properties b/resources/xerces2-j-src/org/apache/xerces/impl/msg/SAXMessages.properties
new file mode 100644
index 0000000..49dbc2b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/msg/SAXMessages.properties
@@ -0,0 +1,46 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces
+# SAX implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id$
+
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n
+
+# JAXP messages
+schema-not-supported = The specified schema language is not supported.
+jaxp-order-not-supported = Property ''{0}'' must be set before setting property ''{1}''.
+schema-already-specified = Property ''{0}'' cannot be set when a non-null Schema object has already been specified.
+
+# feature messages
+feature-not-supported = Feature ''{0}'' is not supported.
+feature-not-recognized = Feature ''{0}'' is not recognized.
+true-not-supported = True state for feature ''{0}'' is not supported.
+false-not-supported = False state for feature ''{0}'' is not supported.
+feature-read-only = Feature ''{0}'' is read only.
+
+# property messages
+property-not-supported = Property ''{0}'' is not supported.
+property-not-recognized = Property ''{0}'' is not recognized.
+property-read-only = Property ''{0}'' is read only.
+property-not-parsing-supported = Property ''{0}'' is not supported while parsing.
+dom-node-read-not-supported = Cannot read DOM node property. No DOM tree exists.
+incompatible-class = The value specified for property ''{0}'' cannot be casted to {1}.
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/msg/XIncludeMessages.properties b/resources/xerces2-j-src/org/apache/xerces/impl/msg/XIncludeMessages.properties
new file mode 100644
index 0000000..c2af19f
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/msg/XIncludeMessages.properties
@@ -0,0 +1,56 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces XInclude implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id$
+
+# Messages for message reporting
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n
+
+# Messages for erroneous input
+NoFallback = An 'include' failed, and no 'fallback' element was found.
+MultipleFallbacks = The [children] of an 'include' element cannot contain more than one 'fallback' element.
+FallbackParent = A 'fallback' element was found that did not have 'include' as the parent.
+IncludeChild = Elements from namespace ''http://www.w3.org/2001/XInclude'', other than ''fallback'', are not allowed to be children of ''include'' elements. However, ''{0}'' was found.
+FallbackChild = Elements from namespace ''http://www.w3.org/2001/XInclude'', other than ''include'', are not allowed to be children of ''fallback'' elements. However, ''{0}'' was found.
+HrefMissing = The 'href' attribute of an 'include' element is missing.
+RecursiveInclude = Recursive include detected. Document ''{0}'' was already processed.
+InvalidParseValue = Invalid value for ''parse'' attribute on ''include'' element: ''{0}''.
+XMLParseError = Error attempting to parse XML file (href=''{0}'').
+XMLResourceError = Include operation failed, reverting to fallback. Resource error reading file as XML (href=''{0}''). Reason: {1}
+TextResourceError = Include operation failed, reverting to fallback. Resource error reading file as text (href=''{0}''). Reason: {1}
+NonDuplicateNotation = Multiple notations were used which had the name ''{0}'', but which were not determined to be duplicates.
+NonDuplicateUnparsedEntity = Multiple unparsed entities were used which had the name ''{0}'', but which were not determined to be duplicates.
+XpointerMissing = xpointer attribute must be present when href attribute is absent.
+AcceptMalformed = Characters outside the range #x20 through #x7E are not allowed in the value of the 'accept' attribute of an 'include' element.
+AcceptLanguageMalformed = Characters outside the range #x20 through #x7E are not allowed in the value of the 'accept-language' attribute of an 'include' element.
+RootElementRequired = A well-formed document requires a root element.
+MultipleRootElements = A well-formed document must not contain multiple root elements.
+ContentIllegalAtTopLevel = The replacement of an 'include' element appearing as the document element in the top-level source infoset cannot contain characters.
+UnexpandedEntityReferenceIllegal = The replacement of an 'include' element appearing as the document element in the top-level source infoset cannot contain unexpanded entity references.
+HrefFragmentIdentifierIllegal = Fragment identifiers must not be used. The ''href'' attribute value ''{0}'' is not permitted.
+HrefSyntacticallyInvalid = ''href'' attribute value ''{0}'' is syntactically invalid. After applying escaping rules the value is neither a syntactically correct URI or IRI.
+XPointerStreamability = An xpointer was specified that points to a location in the source infoset. This location cannot be accessed due to the streaming nature of the processor.
+XPointerResolutionUnsuccessful = XPointer resolution unsuccessful.
+
+# Messages from erroneous set-up
+IncompatibleNamespaceContext = The type of the NamespaceContext is incompatible with using XInclude; it must be an instance of XIncludeNamespaceSupport
+ExpandedSystemId = Could not expand system id of included resource
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/msg/XMLMessageFormatter.java b/resources/xerces2-j-src/org/apache/xerces/impl/msg/XMLMessageFormatter.java
new file mode 100644
index 0000000..a570b5b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/msg/XMLMessageFormatter.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.msg;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.apache.xerces.util.MessageFormatter;
+
+/**
+ * XMLMessageFormatter provides error messages for the XML 1.0 Recommendation and for
+ * the Namespaces Recommendation
+ *
+ * @xerces.internal
+ *
+ * @author Eric Ye, IBM
+ * @version $Id$
+ *
+ */
+public class XMLMessageFormatter implements MessageFormatter {
+ /**
+ * The domain of messages concerning the XML 1.0 specification.
+ */
+ public static final String XML_DOMAIN = "http://www.w3.org/TR/1998/REC-xml-19980210";
+ public static final String XMLNS_DOMAIN = "http://www.w3.org/TR/1999/REC-xml-names-19990114";
+
+ // private objects to cache the locale and resource bundle
+ private Locale fLocale = null;
+ private ResourceBundle fResourceBundle = null;
+
+ //
+ // MessageFormatter methods
+ //
+
+ /**
+ * Formats a message with the specified arguments using the given
+ * locale information.
+ *
+ * @param locale The locale of the message.
+ * @param key The message key.
+ * @param arguments The message replacement text arguments. The order
+ * of the arguments must match that of the placeholders
+ * in the actual message.
+ *
+ * @return Returns the formatted message.
+ *
+ * @throws MissingResourceException Thrown if the message with the
+ * specified key cannot be found.
+ */
+ public String formatMessage(Locale locale, String key, Object[] arguments)
+ throws MissingResourceException {
+
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+ if (locale != fLocale) {
+ fResourceBundle = ResourceBundle.getBundle("org.apache.xerces.impl.msg.XMLMessages", locale);
+ // memorize the most-recent locale
+ fLocale = locale;
+ }
+
+ // format message
+ String msg;
+ try {
+ msg = fResourceBundle.getString(key);
+ if (arguments != null) {
+ try {
+ msg = java.text.MessageFormat.format(msg, arguments);
+ }
+ catch (Exception e) {
+ msg = fResourceBundle.getString("FormatFailed");
+ msg += " " + fResourceBundle.getString(key);
+ }
+ }
+ }
+
+ // error
+ catch (MissingResourceException e) {
+ msg = fResourceBundle.getString("BadMessageKey");
+ throw new MissingResourceException(key, msg, key);
+ }
+
+ // no message
+ if (msg == null) {
+ msg = key;
+ if (arguments.length > 0) {
+ StringBuffer str = new StringBuffer(msg);
+ str.append('?');
+ for (int i = 0; i < arguments.length; i++) {
+ if (i > 0) {
+ str.append('&');
+ }
+ str.append(String.valueOf(arguments[i]));
+ }
+ }
+ }
+
+ return msg;
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/msg/XMLMessages.properties b/resources/xerces2-j-src/org/apache/xerces/impl/msg/XMLMessages.properties
new file mode 100644
index 0000000..c0f1afb
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/msg/XMLMessages.properties
@@ -0,0 +1,313 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file contains error and warning messages related to XML
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id$
+
+ BadMessageKey = The error message corresponding to the message key can not be found.
+ FormatFailed = An internal error occurred while formatting the following message:\n
+
+# Document messages
+ PrematureEOF=Premature end of file.
+# 2.1 Well-Formed XML Documents
+ RootElementRequired = The root element is required in a well-formed document.
+# 2.2 Characters
+ InvalidCharInCDSect = An invalid XML character (Unicode: 0x{0}) was found in the CDATA section.
+ InvalidCharInContent = An invalid XML character (Unicode: 0x{0}) was found in the element content of the document.
+ TwoColonsInQName = An invalid second ':' was found in the element type or attribute name.
+ ColonNotLegalWithNS = A colon is not allowed in the name ''{0}'' when namespaces are enabled.
+ InvalidCharInMisc = An invalid XML character (Unicode: 0x{0}) was found in markup after the end of the element content.
+ InvalidCharInProlog = An invalid XML character (Unicode: 0x{0}) was found in the prolog of the document.
+ InvalidCharInXMLDecl = An invalid XML character (Unicode: 0x{0}) was found in the XML declaration.
+# 2.4 Character Data and Markup
+ CDEndInContent = The character sequence \"]]>\" must not appear in content unless used to mark the end of a CDATA section.
+# 2.7 CDATA Sections
+ CDSectUnterminated = The CDATA section must end with \"]]>\".
+# 2.8 Prolog and Document Type Declaration
+ XMLDeclMustBeFirst = The XML declaration may only appear at the very beginning of the document.
+ EqRequiredInXMLDecl = The '' = '' character must follow \"{0}\" in the XML declaration.
+ QuoteRequiredInXMLDecl = The value following \"{0}\" in the XML declaration must be a quoted string.
+ XMLDeclUnterminated = The XML declaration must end with \"?>\".
+ VersionInfoRequired = The version is required in the XML declaration.
+ SpaceRequiredBeforeVersionInXMLDecl = White space is required before the version pseudo attribute in the XML declaration.
+ SpaceRequiredBeforeEncodingInXMLDecl = White space is required before the encoding pseudo attribute in the XML declaration.
+ SpaceRequiredBeforeStandalone = White space is required before the encoding pseudo attribute in the XML declaration.
+ MarkupNotRecognizedInProlog = The markup in the document preceding the root element must be well-formed.
+ MarkupNotRecognizedInMisc = The markup in the document following the root element must be well-formed.
+ AlreadySeenDoctype = Already seen doctype.
+ DoctypeNotAllowed = DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true.
+ ContentIllegalInProlog = Content is not allowed in prolog.
+ ReferenceIllegalInProlog = Reference is not allowed in prolog.
+# Trailing Misc
+ ContentIllegalInTrailingMisc=Content is not allowed in trailing section.
+ ReferenceIllegalInTrailingMisc=Reference is not allowed in trailing section.
+
+# 2.9 Standalone Document Declaration
+ SDDeclInvalid = The standalone document declaration value must be \"yes\" or \"no\", not \"{0}\".
+# 2.12 Language Identification
+ XMLLangInvalid = The xml:lang attribute value \"{0}\" is an invalid language identifier.
+# 3. Logical Structures
+ ETagRequired = The element type \"{0}\" must be terminated by the matching end-tag \"{0}>\".
+# 3.1 Start-Tags, End-Tags, and Empty-Element Tags
+ ElementUnterminated = Element type \"{0}\" must be followed by either attribute specifications, \">\" or \"/>\".
+ EqRequiredInAttribute = Attribute name \"{1}\" associated with an element type \"{0}\" must be followed by the '' = '' character.
+ OpenQuoteExpected = Open quote is expected for attribute \"{1}\" associated with an element type \"{0}\".
+ CloseQuoteExpected = Close quote is expected for attribute \"{1}\" associated with an element type \"{0}\".
+ AttributeNotUnique = Attribute \"{1}\" was already specified for element \"{0}\".
+ AttributeNSNotUnique = Attribute \"{1}\" bound to namespace \"{2}\" was already specified for element \"{0}\".
+ ETagUnterminated = The end-tag for element type \"{0}\" must end with a ''>'' delimiter.
+ MarkupNotRecognizedInContent = The content of elements must consist of well-formed character data or markup.
+ DoctypeIllegalInContent = A DOCTYPE is not allowed in content.
+# 4.1 Character and Entity References
+ ReferenceUnterminated = The reference must be terminated by a ';' delimiter.
+# 4.3.2 Well-Formed Parsed Entities
+ ReferenceNotInOneEntity = The reference must be entirely contained within the same parsed entity.
+ ElementEntityMismatch = The element \"{0}\" must start and end within the same entity.
+ MarkupEntityMismatch=XML document structures must start and end within the same entity.
+
+# Messages common to Document and DTD
+# 2.2 Characters
+ InvalidCharInAttValue = An invalid XML character (Unicode: 0x{2}) was found in the value of attribute \"{1}\" and element is \"{0}\".
+ InvalidCharInComment = An invalid XML character (Unicode: 0x{0}) was found in the comment.
+ InvalidCharInPI = An invalid XML character (Unicode: 0x{0}) was found in the processing instruction.
+ InvalidCharInInternalSubset = An invalid XML character (Unicode: 0x{0}) was found in the internal subset of the DTD.
+ InvalidCharInTextDecl = An invalid XML character (Unicode: 0x{0}) was found in the text declaration.
+# 2.3 Common Syntactic Constructs
+ QuoteRequiredInAttValue = The value of attribute \"{1}\" must begin with either a single or double quote character.
+ LessthanInAttValue = The value of attribute \"{1}\" associated with an element type \"{0}\" must not contain the ''<'' character.
+ AttributeValueUnterminated = The value for attribute \"{1}\" must end with the matching quote character.
+# 2.5 Comments
+ InvalidCommentStart = Comment must start with \"\".
+ COMMENT_NOT_IN_ONE_ENTITY = The comment is not enclosed in the same entity.
+# 2.6 Processing Instructions
+ PITargetRequired = The processing instruction must begin with the name of the target.
+ SpaceRequiredInPI = White space is required between the processing instruction target and data.
+ PIUnterminated = The processing instruction must end with \"?>\".
+ ReservedPITarget = The processing instruction target matching \"[xX][mM][lL]\" is not allowed.
+ PI_NOT_IN_ONE_ENTITY = The processing instruction is not enclosed in the same entity.
+# 2.8 Prolog and Document Type Declaration
+ VersionInfoInvalid = Invalid version \"{0}\".
+ VersionNotSupported = XML version \"{0}\" is not supported, only XML 1.0 is supported.
+ VersionNotSupported11 = XML version \"{0}\" is not supported, only XML 1.0 and XML 1.1 are supported.
+# 4.1 Character and Entity References
+ DigitRequiredInCharRef = A decimal representation must immediately follow the \"\" in a character reference.
+ HexdigitRequiredInCharRef = A hexadecimal representation must immediately follow the \"\" in a character reference.
+ SemicolonRequiredInCharRef = The character reference must end with the ';' delimiter.
+ InvalidCharRef = Character reference \"{0}\" is an invalid XML character.
+ NameRequiredInReference = The entity name must immediately follow the '&' in the entity reference.
+ SemicolonRequiredInReference = The reference to entity \"{0}\" must end with the '';'' delimiter.
+# 4.3.1 The Text Declaration
+ TextDeclMustBeFirst = The text declaration may only appear at the very beginning of the external parsed entity.
+ EqRequiredInTextDecl = The '' = '' character must follow \"{0}\" in the text declaration.
+ QuoteRequiredInTextDecl = The value following \"{0}\" in the text declaration must be a quoted string.
+ CloseQuoteMissingInTextDecl = closing quote in the value following \"{0}\" in the text declaration is missing.
+ SpaceRequiredBeforeVersionInTextDecl = White space is required before the version pseudo attribute in the text declaration.
+ SpaceRequiredBeforeEncodingInTextDecl = White space is required before the encoding pseudo attribute in the text declaration.
+ TextDeclUnterminated = The text declaration must end with \"?>\".
+ EncodingDeclRequired = The encoding declaration is required in the text declaration.
+ NoMorePseudoAttributes = No more pseudo attributes are allowed.
+ MorePseudoAttributes = More pseudo attributes are expected.
+ PseudoAttrNameExpected = A pseudo attribute name is expected.
+# 4.3.2 Well-Formed Parsed Entities
+ CommentNotInOneEntity = The comment must be entirely contained within the same parsed entity.
+ PINotInOneEntity = The processing instruction must be entirely contained within the same parsed entity.
+# 4.3.3 Character Encoding in Entities
+ EncodingDeclInvalid = Invalid encoding name \"{0}\".
+ EncodingByteOrderUnsupported = Given byte order for encoding \"{0}\" is not supported.
+ InvalidByte = Invalid byte {0} of {1}-byte UTF-8 sequence.
+ ExpectedByte = Expected byte {0} of {1}-byte UTF-8 sequence.
+ InvalidHighSurrogate = High surrogate bits in UTF-8 sequence must not exceed 0x10 but found 0x{0}.
+ OperationNotSupported = Operation \"{0}\" not supported by {1} reader.
+ InvalidASCII = Byte \"{0}\" is not a member of the (7-bit) ASCII character set.
+ CharConversionFailure = An entity determined to be in a certain encoding must not contain sequences illegal in that encoding.
+
+# DTD Messages
+# 2.2 Characters
+ InvalidCharInEntityValue = An invalid XML character (Unicode: 0x{0}) was found in the literal entity value.
+ InvalidCharInExternalSubset = An invalid XML character (Unicode: 0x{0}) was found in the external subset of the DTD.
+ InvalidCharInIgnoreSect = An invalid XML character (Unicode: 0x{0}) was found in the excluded conditional section.
+ InvalidCharInPublicID = An invalid XML character (Unicode: 0x{0}) was found in the public identifier.
+ InvalidCharInSystemID = An invalid XML character (Unicode: 0x{0}) was found in the system identifier.
+# 2.3 Common Syntactic Constructs
+ SpaceRequiredAfterSYSTEM = White space is required after keyword SYSTEM in DOCTYPE decl.
+ QuoteRequiredInSystemID = The system identifier must begin with either a single or double quote character.
+ SystemIDUnterminated = The system identifier must end with the matching quote character.
+ SpaceRequiredAfterPUBLIC = White spaces are required after keyword PUBLIC in DOCTYPE decl.
+ QuoteRequiredInPublicID = The public identifier must begin with either a single or double quote character.
+ PublicIDUnterminated = The public identifier must end with the matching quote character.
+ PubidCharIllegal = The character (Unicode: 0x{0}) is not permitted in the public identifier.
+ SpaceRequiredBetweenPublicAndSystem = White spaces are required between publicId and systemId.
+# 2.8 Prolog and Document Type Declaration
+ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = White space is required after \"''.
+ PEReferenceWithinMarkup = The parameter entity reference \"%{0};\" cannot occur within markup in the internal subset of the DTD.
+ MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = The markup declarations contained or pointed to by the document type declaration must be well-formed.
+# 2.10 White Space Handling
+ MSG_XML_SPACE_DECLARATION_ILLEGAL = The attribute declaration for \"xml:space\" must be given as an enumerated type whose only possible values are \"default\" and \"preserve\".
+# 3.2 Element Type Declarations
+ MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ELEMENTDECL = White space is required after \"''.
+# 3.2.1 Element Content
+ MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN = A ''('' character or an element type is required in the declaration of element type \"{0}\".
+ MSG_CLOSE_PAREN_REQUIRED_IN_CHILDREN = A '')'' is required in the declaration of element type \"{0}\".
+# 3.2.2 Mixed Content
+ MSG_ELEMENT_TYPE_REQUIRED_IN_MIXED_CONTENT = An element type is required in the declaration of element type \"{0}\".
+ MSG_CLOSE_PAREN_REQUIRED_IN_MIXED = A '')'' is required in the declaration of element type \"{0}\".
+ MixedContentUnterminated = The mixed content model \"{0}\" must end with \")*\" when the types of child elements are constrained.
+# 3.3 Attribute-List Declarations
+ MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ATTLISTDECL = White space is required after \"\".
+ IgnoreSectUnterminated = The excluded conditional section must end with \"]]>\".
+# 4.1 Character and Entity References
+ NameRequiredInPEReference = The entity name must immediately follow the '%' in the parameter entity reference.
+ SemicolonRequiredInPEReference = The parameter entity reference \"%{0};\" must end with the '';'' delimiter.
+# 4.2 Entity Declarations
+ MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_ENTITYDECL = White space is required after \"''.
+ MSG_DUPLICATE_ENTITY_DEFINITION = Entity \"{0}\" is declared more than once.
+# 4.2.2 External Entities
+ ExternalIDRequired = The external entity declaration must begin with either \"SYSTEM\" or \"PUBLIC\".
+ MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = White space is required between \"PUBLIC\" and the public identifier.
+ MSG_SPACE_REQUIRED_AFTER_PUBIDLITERAL_IN_EXTERNALID = White space is required between the public identifier and the system identifier.
+ MSG_SPACE_REQUIRED_BEFORE_SYSTEMLITERAL_IN_EXTERNALID = White space is required between \"SYSTEM\" and the system identifier.
+ MSG_URI_FRAGMENT_IN_SYSTEMID = The fragment identifier should not be specified as part of the system identifier \"{0}\".
+# 4.7 Notation Declarations
+ MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_NOTATIONDECL = White space is required after \"''.
+
+# Validation messages
+ DuplicateTypeInMixedContent = The element type \"{1}\" was already specified in the content model of the element decl \"{0}\".
+ ENTITIESInvalid = Attribute value \"{1}\" of type ENTITIES must be the names of one or more unparsed entities.
+ ENTITYInvalid = Attribute value \"{1}\" of type ENTITY must be the name of an unparsed entity.
+ IDDefaultTypeInvalid = The ID attribute \"{0}\" must have a declared default of \"#IMPLIED\" or \"#REQUIRED\".
+ IDInvalid = Attribute value \"{0}\" of type ID must be a name.
+ IDInvalidWithNamespaces = Attribute value \"{0}\" of type ID must be an NCName when namespaces are enabled.
+ IDNotUnique = Attribute value \"{0}\" of type ID must be unique within the document.
+ IDREFInvalid = Attribute value \"{0}\" of type IDREF must be a name.
+ IDREFInvalidWithNamespaces = Attribute value \"{0}\" of type IDREF must be an NCName when namespaces are enabled.
+ IDREFSInvalid = Attribute value \"{0}\" of type IDREFS must be one or more names.
+ ILL_FORMED_PARAMETER_ENTITY_WHEN_USED_IN_DECL = The replacement text of parameter entity \"{0}\" must include properly nested declarations when the entity reference is used as a complete declaration.
+ ImproperDeclarationNesting = The replacement text of parameter entity \"{0}\" must include properly nested declarations.
+ ImproperGroupNesting = The replacement text of parameter entity \"{0}\" must include properly nested pairs of parentheses.
+ INVALID_PE_IN_CONDITIONAL = The replacement text of parameter entity \"{0}\" must include the entire conditional section or just INCLUDE or IGNORE.
+ MSG_ATTRIBUTE_NOT_DECLARED = Attribute \"{1}\" must be declared for element type \"{0}\".
+ MSG_ATTRIBUTE_VALUE_NOT_IN_LIST = Attribute \"{0}\" with value \"{1}\" must have a value from the list \"{2}\".
+ MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE = The value \"{1}\" of attribute \"{0}\" must not be changed by normalization (to \"{2}\") in a standalone document.
+ MSG_CONTENT_INCOMPLETE = The content of element type \"{0}\" is incomplete, it must match \"{1}\".
+ MSG_CONTENT_INVALID = The content of element type \"{0}\" must match \"{1}\".
+ MSG_CONTENT_INVALID_SPECIFIED = The content of element type \"{0}\" must match \"{1}\". Children of type \"{2}\" are not allowed.
+ MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED = Attribute \"{1}\" for element type \"{0}\" has a default value and must be specified in a standalone document.
+ MSG_DUPLICATE_ATTDEF = Attribute \"{1}\" is already declared for element type \"{0}\".
+ MSG_ELEMENT_ALREADY_DECLARED = Element type \"{0}\" must not be declared more than once.
+ MSG_ELEMENT_NOT_DECLARED = Element type \"{0}\" must be declared.
+ MSG_GRAMMAR_NOT_FOUND = Document is invalid: no grammar found.
+ MSG_ELEMENT_WITH_ID_REQUIRED = An element with the identifier \"{0}\" must appear in the document.
+ MSG_EXTERNAL_ENTITY_NOT_PERMITTED = The reference to external entity \"{0}\" is not permitted in a standalone document.
+ MSG_FIXED_ATTVALUE_INVALID = Attribute \"{1}\" with value \"{2}\" must have a value of \"{3}\".
+ MSG_MORE_THAN_ONE_ID_ATTRIBUTE = Element type \"{0}\" already has attribute \"{1}\" of type ID, a second attribute \"{2}\" of type ID is not permitted.
+ MSG_MORE_THAN_ONE_NOTATION_ATTRIBUTE = Element type \"{0}\" already has attribute \"{1}\" of type NOTATION, a second attribute \"{2}\" of type NOTATION is not permitted.
+ MSG_NOTATION_NOT_DECLARED_FOR_NOTATIONTYPE_ATTRIBUTE = The notation \"{1}\" must be declared when referenced in the notation type list for attribute \"{0}\".
+ MSG_NOTATION_NOT_DECLARED_FOR_UNPARSED_ENTITYDECL = The notation \"{1}\" must be declared when referenced in the unparsed entity declaration for \"{0}\".
+ MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE = The reference to entity \"{0}\" declared in the external subset of the DTD or in a parameter entity is not permitted in a standalone document.
+ MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED = Attribute \"{1}\" is required and must be specified for element type \"{0}\".
+ MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE = In a standalone document white space must not occur between elements with element content which are declared in the external subset of the DTD or in a parameter entity.
+ NMTOKENInvalid = Attribute value \"{0}\" of type NMTOKEN must be a name token.
+ NMTOKENSInvalid = Attribute value \"{0}\" of type NMTOKENS must be one or more name tokens.
+ NoNotationOnEmptyElement = Element type \"{0}\" which was declared EMPTY cannot declare attribute \"{1}\" of type NOTATION.
+ RootElementTypeMustMatchDoctypedecl = Document root element \"{1}\", must match DOCTYPE root \"{0}\".
+ UndeclaredElementInContentSpec = The content model of element \"{0}\" refers to the undeclared element \"{1}\".
+ UniqueNotationName = The declaration for the notation \"{0}\" is not unique. A given Name must not be declared in more than one notation declaration.
+ ENTITYFailedInitializeGrammar = ENTITYDatatype Validator: Failed Need to call initialize method with a valid Grammar reference.
+ ENTITYNotUnparsed = ENTITY \"{0}\" is not unparsed.
+ ENTITYNotValid = ENTITY \"{0}\" is not valid.
+ EmptyList = Value of type ENTITIES, IDREFS, and NMTOKENS cannot be empty list.
+
+# Entity related messages
+# 3.1 Start-Tags, End-Tags, and Empty-Element Tags
+ ReferenceToExternalEntity = The external entity reference \"&{0};\" is not permitted in an attribute value.
+# 4.1 Character and Entity References
+ EntityNotDeclared = The entity \"{0}\" was referenced, but not declared.
+ ReferenceToUnparsedEntity = The unparsed entity reference \"&{0};\" is not permitted.
+ RecursiveReference = Recursive entity reference \"{0}\". (Reference path: {1}),
+ RecursiveGeneralReference = Recursive general entity reference \"&{0};\". (Reference path: {1}),
+ RecursivePEReference = Recursive parameter entity reference \"%{0};\". (Reference path: {1}),
+# 4.3.3 Character Encoding in Entities
+ EncodingNotSupported = The encoding \"{0}\" is not supported.
+ EncodingRequired = A parsed entity not encoded in either UTF-8 or UTF-16 must contain an encoding declaration.
+
+# Namespaces support
+# 4. Using Qualified Names
+ IllegalQName = Element or attribute do not match QName production: QName::=(NCName':')?NCName.
+ ElementXMLNSPrefix = Element \"{0}\" cannot have \"xmlns\" as its prefix.
+ ElementPrefixUnbound = The prefix \"{0}\" for element \"{1}\" is not bound.
+ AttributePrefixUnbound = The prefix \"{2}\" for attribute \"{1}\" associated with an element type \"{0}\" is not bound.
+ EmptyPrefixedAttName = The value of the attribute \"{0}\" is invalid. Prefixed namespace bindings may not be empty.
+ PrefixDeclared = The namespace prefix \"{0}\" was not declared.
+ CantBindXMLNS = The prefix "xmlns" cannot be bound to any namespace explicitly; neither can the namespace for "xmlns" be bound to any prefix explicitly.
+ CantBindXML = The prefix "xml" cannot be bound to any namespace other than its usual namespace; neither can the namespace for "xml" be bound to any prefix other than "xml".
+ MSG_ATT_DEFAULT_INVALID = The defaultValue \"{1}\" of attribute \"{0}\" is not legal as for the lexical constraints of this attribute type.
+
+# REVISIT: These need messages
+ MSG_SPACE_REQUIRED_AFTER_SYSTEMLITERAL_IN_EXTERNALID=MSG_SPACE_REQUIRED_AFTER_SYSTEMLITERAL_IN_EXTERNALID
+ OpenQuoteMissingInDecl=OpenQuoteMissingInDecl
+ InvalidCharInLiteral=InvalidCharInLiteral
+
+
+#Application can set the limit of number of entities that should be expanded by the parser.
+EntityExpansionLimitExceeded=The parser has encountered more than \"{0}\" entity expansions in this document; this is the limit imposed by the application.
+
+#Application can set limits on the size of entities that should be processed by the parser.
+TotalEntitySizeLimitExceeded=The parser has encountered more than \"{0}\" bytes or characters within entities declared and referenced by this document; this is the limit imposed by the application.
+MaxGeneralEntitySizeLimitExceeded=The parser has encountered more than \"{0}\" bytes or characters within a general entity; this is the limit imposed by the application.
+MaxParameterEntitySizeLimitExceeded=The parser has encountered more than \"{0}\" bytes or characters within a parameter entity; this is the limit imposed by the application.
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/msg/XMLSchemaMessages.properties b/resources/xerces2-j-src/org/apache/xerces/impl/msg/XMLSchemaMessages.properties
new file mode 100644
index 0000000..7957716
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/msg/XMLSchemaMessages.properties
@@ -0,0 +1,321 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file contains error and warning messages related to XML Schema
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id$
+
+ BadMessageKey = The error message corresponding to the message key can not be found.
+ FormatFailed = An internal error occurred while formatting the following message:\n
+
+# For internal use
+
+ Internal-Error = Internal error: {0}.
+ dt-whitespace = Whitespace facet value is not available for the union simpleType ''{0}''
+ GrammarConflict = One of the grammar(s) returned from the user's grammar pool is in conflict with another grammar.
+
+# Identity constraints
+
+ AbsentKeyValue = cvc-identity-constraint.4.2.1.a: Element \"{0}\" has no value for the key \"{1}\".
+ DuplicateField = Duplicate match in scope for field \"{0}\".
+ DuplicateKey = cvc-identity-constraint.4.2.2: Duplicate key value [{0}] declared for identity constraint \"{2}\" of element \"{1}\".
+ DuplicateUnique = cvc-identity-constraint.4.1: Duplicate unique value [{0}] declared for identity constraint \"{2}\" of element \"{1}\".
+ FieldMultipleMatch = cvc-identity-constraint.3: Field \"{0}\" of identity constraint \"{1}\" matches more than one value within the scope of its selector; fields must match unique values.
+ FixedDiffersFromActual = The content of this element is not equivalent to the value of the \"fixed\" attribute in the element's declaration in the schema.
+ KeyMatchesNillable = cvc-identity-constraint.4.2.3: Element \"{0}\" has the key \"{1}\" which matches an element which has nillable set to true.
+ KeyNotEnoughValues = cvc-identity-constraint.4.2.1.b: Not enough values specified for identity constraint specified for element \"{0}\".
+ KeyNotFound = cvc-identity-constraint.4.3: Key ''{0}'' with value ''{1}'' not found for identity constraint of element ''{2}''.
+ KeyRefOutOfScope = Identity Constraint error: identity constraint \"{0}\" has a keyref which refers to a key or unique that is out of scope.
+ KeyRefReferNotFound = Key reference declaration \"{0}\" refers to unknown key with name \"{1}\".
+ UnknownField = Internal identity constraint error; unknown field \"{0}\" for identity constraint \"{2}\" specified for element \"{1}\".
+
+# Ideally, we should only use the following error keys, not the ones under
+# "Identity constraints". And we should cover all of the following errors.
+
+#validation (3.X.4)
+
+ cvc-attribute.3 = cvc-attribute.3: The value ''{2}'' of attribute ''{1}'' on element ''{0}'' is not valid with respect to its type, ''{3}''.
+ cvc-attribute.4 = cvc-attribute.4: The value ''{2}'' of attribute ''{1}'' on element ''{0}'' is not valid with respect to its fixed '{'value constraint'}'. The attribute must have a value of ''{3}''.
+ cvc-complex-type.2.1 = cvc-complex-type.2.1: Element ''{0}'' must have no character or element information item [children], because the type''s content type is empty.
+ cvc-complex-type.2.2 = cvc-complex-type.2.2: Element ''{0}'' must have no element [children], and the value must be valid.
+ cvc-complex-type.2.3 = cvc-complex-type.2.3: Element ''{0}'' cannot have character [children], because the type''s content type is element-only.
+ cvc-complex-type.2.4.a = cvc-complex-type.2.4.a: Invalid content was found starting with element ''{0}''. One of ''{1}'' is expected.
+ cvc-complex-type.2.4.b = cvc-complex-type.2.4.b: The content of element ''{0}'' is not complete. One of ''{1}'' is expected.
+ cvc-complex-type.2.4.c = cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element ''{0}''.
+ cvc-complex-type.2.4.d = cvc-complex-type.2.4.d: Invalid content was found starting with element ''{0}''. No child element is expected at this point.
+ cvc-complex-type.2.4.e = cvc-complex-type.2.4.e: ''{0}'' can occur a maximum of ''{2}'' times in the current sequence. This limit was exceeded. At this point one of ''{1}'' is expected.
+ cvc-complex-type.2.4.f = cvc-complex-type.2.4.f: ''{0}'' can occur a maximum of ''{1}'' times in the current sequence. This limit was exceeded. No child element is expected at this point.
+ cvc-complex-type.2.4.g = cvc-complex-type.2.4.g: Invalid content was found starting with element ''{0}''. ''{1}'' is expected to occur a minimum of ''{2}'' times in the current sequence. One more instance is required to satisfy this constraint.
+ cvc-complex-type.2.4.h = cvc-complex-type.2.4.h: Invalid content was found starting with element ''{0}''. ''{1}'' is expected to occur a minimum of ''{2}'' times in the current sequence. ''{3}'' more instances are required to satisfy this constraint.
+ cvc-complex-type.2.4.i = cvc-complex-type.2.4.i: The content of element ''{0}'' is not complete. ''{1}'' is expected to occur a minimum of ''{2}'' times. One more instance is required to satisfy this constraint.
+ cvc-complex-type.2.4.j = cvc-complex-type.2.4.j: The content of element ''{0}'' is not complete. ''{1}'' is expected to occur a minimum of ''{2}'' times. ''{3}'' more instances are required to satisfy this constraint.
+ cvc-complex-type.3.1 = cvc-complex-type.3.1: Value ''{2}'' of attribute ''{1}'' of element ''{0}'' is not valid with respect to the corresponding attribute use. Attribute ''{1}'' has a fixed value of ''{3}''.
+ cvc-complex-type.3.2.1 = cvc-complex-type.3.2.1: Element ''{0}'' does not have an attribute wildcard for attribute ''{1}''.
+ cvc-complex-type.3.2.2 = cvc-complex-type.3.2.2: Attribute ''{1}'' is not allowed to appear in element ''{0}''.
+ cvc-complex-type.4 = cvc-complex-type.4: Attribute ''{1}'' must appear on element ''{0}''.
+ cvc-complex-type.5.1 = cvc-complex-type.5.1: In element ''{0}'', attribute ''{1}'' is a Wild ID. But there is already a Wild ID ''{2}''. There can be only one.
+ cvc-complex-type.5.2 = cvc-complex-type.5.2: In element ''{0}'', attribute ''{1}'' is a Wild ID. But there is already an attribute ''{2}'' derived from ID among the '{'attribute uses'}'.
+ cvc-datatype-valid.1.2.1 = cvc-datatype-valid.1.2.1: ''{0}'' is not a valid value for ''{1}''.
+ cvc-datatype-valid.1.2.2 = cvc-datatype-valid.1.2.2: ''{0}'' is not a valid value of list type ''{1}''.
+ cvc-datatype-valid.1.2.3 = cvc-datatype-valid.1.2.3: ''{0}'' is not a valid value of union type ''{1}''.
+ cvc-elt.1.a = cvc-elt.1.a: Cannot find the declaration of element ''{0}''.
+ cvc-elt.1.b = cvc-elt.1.b: The name of the element does not match the name of the element declaration. Saw ''{0}''. Expected ''{1}''.
+ cvc-elt.2 = cvc-elt.2: The value of '{'abstract'}' in the element declaration for ''{0}'' must be false.
+ cvc-elt.3.1 = cvc-elt.3.1: Attribute ''{1}'' must not appear on element ''{0}'', because the '{'nillable'}' property of ''{0}'' is false.
+ cvc-elt.3.2.1 = cvc-elt.3.2.1: Element ''{0}'' cannot have character or element information [children], because ''{1}'' is specified.
+ cvc-elt.3.2.2 = cvc-elt.3.2.2: There must be no fixed '{'value constraint'}' for element ''{0}'', because ''{1}'' is specified.
+ cvc-elt.4.1 = cvc-elt.4.1: The value ''{2}'' of attribute ''{1}'' of element ''{0}'' is not a valid QName.
+ cvc-elt.4.2 = cvc-elt.4.2: Cannot resolve ''{1}'' to a type definition for element ''{0}''.
+ cvc-elt.4.3 = cvc-elt.4.3: Type ''{1}'' is not validly derived from the type definition, ''{2}'', of element ''{0}''.
+ cvc-elt.5.1.1 = cvc-elt.5.1.1: '{'value constraint'}' ''{2}'' of element ''{0}'' is not a valid default value for type ''{1}''.
+ cvc-elt.5.2.2.1 = cvc-elt.5.2.2.1: Element ''{0}'' must have no element information item [children].
+ cvc-elt.5.2.2.2.1 = cvc-elt.5.2.2.2.1: The value ''{1}'' of element ''{0}'' does not match the fixed '{'value constraint'}' value ''{2}''.
+ cvc-elt.5.2.2.2.2 = cvc-elt.5.2.2.2.2: The value ''{1}'' of element ''{0}'' does not match the '{'value constraint'}' value ''{2}''.
+ cvc-enumeration-valid = cvc-enumeration-valid: Value ''{0}'' is not facet-valid with respect to enumeration ''{1}''. It must be a value from the enumeration.
+ cvc-fractionDigits-valid = cvc-fractionDigits-valid: Value ''{0}'' has {1} fraction digits, but the number of fraction digits has been limited to {2}.
+ cvc-id.1 = cvc-id.1: There is no ID/IDREF binding for IDREF ''{0}''.
+ cvc-id.2 = cvc-id.2: There are multiple occurrences of ID value ''{0}''.
+ cvc-id.3 = cvc-id.3: A field of identity constraint ''{0}'' matched element ''{1}'', but this element does not have a simple type.
+ cvc-length-valid = cvc-length-valid: Value ''{0}'' with length = ''{1}'' is not facet-valid with respect to length ''{2}'' for type ''{3}''.
+ cvc-maxExclusive-valid = cvc-maxExclusive-valid: Value ''{0}'' is not facet-valid with respect to maxExclusive ''{1}'' for type ''{2}''.
+ cvc-maxInclusive-valid = cvc-maxInclusive-valid: Value ''{0}'' is not facet-valid with respect to maxInclusive ''{1}'' for type ''{2}''.
+ cvc-maxLength-valid = cvc-maxLength-valid: Value ''{0}'' with length = ''{1}'' is not facet-valid with respect to maxLength ''{2}'' for type ''{3}''.
+ cvc-minExclusive-valid = cvc-minExclusive-valid: Value ''{0}'' is not facet-valid with respect to minExclusive ''{1}'' for type ''{2}''.
+ cvc-minInclusive-valid = cvc-minInclusive-valid: Value ''{0}'' is not facet-valid with respect to minInclusive ''{1}'' for type ''{2}''.
+ cvc-minLength-valid = cvc-minLength-valid: Value ''{0}'' with length = ''{1}'' is not facet-valid with respect to minLength ''{2}'' for type ''{3}''.
+ cvc-pattern-valid = cvc-pattern-valid: Value ''{0}'' is not facet-valid with respect to pattern ''{1}'' for type ''{2}''.
+ cvc-totalDigits-valid = cvc-totalDigits-valid: Value ''{0}'' has {1} total digits, but the number of total digits has been limited to {2}.
+ cvc-type.1 = cvc-type.1: The type definition ''{0}'' was not found.
+ cvc-type.2 = cvc-type.2: The type definition cannot be abstract for element {0}.
+ cvc-type.3.1.1 = cvc-type.3.1.1: Element ''{0}'' is a simple type, so it cannot have attributes, excepting those whose namespace name is identical to ''http://www.w3.org/2001/XMLSchema-instance'' and whose [local name] is one of ''type'', ''nil'', ''schemaLocation'' or ''noNamespaceSchemaLocation''. However, the attribute, ''{1}'' was found.
+ cvc-type.3.1.2 = cvc-type.3.1.2: Element ''{0}'' is a simple type, so it must have no element information item [children].
+ cvc-type.3.1.3 = cvc-type.3.1.3: The value ''{1}'' of element ''{0}'' is not valid.
+
+#schema valid (3.X.3)
+
+ schema_reference.4 = schema_reference.4: Failed to read schema document ''{0}'', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not .
+ src-annotation = src-annotation: elements can only contain and elements, but ''{0}'' was found.
+ src-attribute.1 = src-attribute.1: The properties ''default'' and ''fixed'' cannot both be present in attribute declaration ''{0}''. Use only one of them.
+ src-attribute.2 = src-attribute.2: : The property ''default'' is present in attribute ''{0}'', so the value of ''use'' must be ''optional''.
+ src-attribute.3.1 = src-attribute.3.1: One of 'ref' or 'name' must be present in a local attribute declaration.
+ src-attribute.3.2 = src-attribute.3.2: The content must match (annotation?) for the attribute reference ''{0}''.
+ src-attribute.4 = src-attribute.4: Attribute ''{0}'' has both a ''type'' attribute and an anonymous ''simpleType'' child. Only one of these is allowed for an attribute.
+ src-attribute_group.2 = src-attribute_group.2: The intersection of wildcards is not expressible for attribute group ''{0}''.
+ src-attribute_group.3 = src-attribute_group.3: Circular definitions detected for attribute group ''{0}''. Recursively following attribute group references eventually leads back to itself.
+ src-ct.1 = src-ct.1: Complex Type Definition Representation Error for type ''{0}''. When is used, the base type must be a complexType. ''{1}'' is a simpleType.
+ src-ct.2.1 = src-ct.2.1: Complex Type Definition Representation Error for type ''{0}''. When is used, the base type must be a complexType whose content type is simple, or, only if restriction is specified, a complex type with mixed content and emptiable particle, or, only if extension is specified, a simple type. ''{1}'' satisfies none of these conditions.
+ src-ct.2.2 = src-ct.2.2: Complex Type Definition Representation Error for type ''{0}''. When a complexType with simpleContent restricts a complexType with mixed content and emptiable particle, then there must be a among the children of .
+ src-ct.4 = src-ct.4: Complex Type Definition Representation Error for type ''{0}''. The intersection of wildcards is not expressible.
+ src-ct.5 = src-ct.5: Complex Type Definition Representation Error for type ''{0}''. The union of wildcards is not expressible.
+ src-element.1 = src-element.1: The properties ''default'' and ''fixed'' cannot both be present in element declaration ''{0}''. Use only one of them.
+ src-element.2.1 = src-element.2.1: : One of 'ref' or 'name' must be present in a local element declaration.
+ src-element.2.2 = src-element.2.2: Since ''{0}'' contains the ''ref'' attribute, its content must match (annotation?). However, ''{1}'' was found.
+ src-element.3 = src-element.3: Element ''{0}'' has both a ''type'' attribute and a ''anonymous type'' child. Only one of these is allowed for an element.
+ src-import.1.1 = src-import.1.1: The namespace attribute ''{0}'' of an element information item must not be the same as the targetNamespace of the schema it exists in.
+ src-import.1.2 = src-import.1.2: If the namespace attribute is not present on an element information item then the enclosing schema must have a targetNamespace.
+ src-import.2 = src-import.2: The root element of document ''{0}'' has to have the namespace name ''http://www.w3.org/2001/XMLSchema'' and the local name ''schema''.
+ src-import.3.1 = src-import.3.1: The namespace attribute, ''{0}'', of an element information item must be identical to the targetNamespace attribute, ''{1}'', of the imported document.
+ src-import.3.2 = src-import.3.2: An element information item that had no namespace attribute was found, so the imported document cannot have a targetNamespace attribute. However, the targetNamespace ''{1}'' was found in the imported document.
+ src-include.1 = src-include.1: The root element of document ''{0}'' has to have the namespace name ''http://www.w3.org/2001/XMLSchema'' and the local name ''schema''.
+ src-include.2.1 = src-include.2.1: The targetNamespace of the referenced schema, currently ''{1}'', must be identical to that of the including schema, currently ''{0}''.
+ src-redefine.2 = src-redefine.2: The root element of document ''{0}'' has to have the namespace name ''http://www.w3.org/2001/XMLSchema'' and the local name ''schema''.
+ src-redefine.3.1 = src-redefine.3.1: The targetNamespace of the referenced schema, currently ''{1}'', must be identical to that of the redefining schema, currently ''{0}''.
+ src-redefine.5.a.a = src-redefine.5.a.a: No non-annotation children of were found. children of elements must have descendants, with 'base' attributes that refer to themselves.
+ src-redefine.5.a.b = src-redefine.5.a.b: ''{0}'' is not a valid child element. children of elements must have descendants, with ''base'' attributes that refer to themselves.
+ src-redefine.5.a.c = src-redefine.5.a.c: ''{0}'' does not have a ''base'' attribute that refers to the redefined element, ''{1}''. children of elements must have descendants, with ''base'' attributes that refer to themselves.
+ src-redefine.5.b.a = src-redefine.5.b.a: No non-annotation children of were found. children of elements must have or descendants, with 'base' attributes that refer to themselves.
+ src-redefine.5.b.b = src-redefine.5.b.b: No non-annotation grandchildren of were found. children of elements must have or descendants, with 'base' attributes that refer to themselves.
+ src-redefine.5.b.c = src-redefine.5.b.c: ''{0}'' is not a valid grandchild element. children of elements must have or descendants, with ''base'' attributes that refer to themselves.
+ src-redefine.5.b.d = src-redefine.5.b.d: ''{0}'' does not have a ''base'' attribute that refers to the redefined element, ''{1}''. children of elements must have or descendants, with ''base'' attributes that refer to themselves.
+ src-redefine.6.1.1 = src-redefine.6.1.1: If a group child of a element contains a group referring itself, it must have exactly 1; this one has ''{0}''.
+ src-redefine.6.1.2 = src-redefine.6.1.2: The group ''{0}'', which contains a reference to a group being redefined, must have ''minOccurs'' = ''maxOccurs'' = 1.
+ src-redefine.6.2.1 = src-redefine.6.2.1: No group in the redefined schema has a name matching ''{0}''.
+ src-redefine.6.2.2 = src-redefine.6.2.2: Group ''{0}'' does not properly restrict the group it redefines; constraint violated: ''{1}''.
+ src-redefine.7.1 = src-redefine.7.1: If an attributeGroup child of a element contains an attributeGroup referring itself, it must have exactly 1; this one has {0}.
+ src-redefine.7.2.1 = src-redefine.7.2.1: No attributeGroup in the redefined schema has a name matching ''{0}''.
+ src-redefine.7.2.2 = src-redefine.7.2.2: AttributeGroup ''{0}'' does not properly restrict the attributeGroup it redefines; constraint violated: ''{1}''.
+ src-resolve = src-resolve: Cannot resolve the name ''{0}'' to a(n) ''{1}'' component.
+ src-resolve.4.1 = src-resolve.4.1: Error resolving component ''{2}''. It was detected that ''{2}'' has no namespace, but components with no target namespace are not referenceable from schema document ''{0}''. If ''{2}'' is intended to have a namespace, perhaps a prefix needs to be provided. If it is intended that ''{2}'' has no namespace, then an ''import'' without a "namespace" attribute should be added to ''{0}''.
+ src-resolve.4.2 = src-resolve.4.2: Error resolving component ''{2}''. It was detected that ''{2}'' is in namespace ''{1}'', but components from this namespace are not referenceable from schema document ''{0}''. If this is the incorrect namespace, perhaps the prefix of ''{2}'' needs to be changed. If this is the correct namespace, then an appropriate ''import'' tag should be added to ''{0}''.
+ src-simple-type.2.a = src-simple-type.2.a: A element was found that has both a base [attribute] and a element among its [children]. Only one is allowed.
+ src-simple-type.2.b = src-simple-type.2.b: A element was found that has neither a base [attribute] nor a element among its [children]. One is required.
+ src-simple-type.3.a = src-simple-type.3.a: A element was found that has both an itemType [attribute] and a element among its [children]. Only one is allowed.
+ src-simple-type.3.b = src-simple-type.3.b: A element was found that has neither an itemType [attribute] nor a element among its [children]. One is required.
+ src-single-facet-value = src-single-facet-value: The facet ''{0}'' is defined more than once.
+ src-union-memberTypes-or-simpleTypes = src-union-memberTypes-or-simpleTypes: A element must have either a non-empty memberTypes [attribute] or at least one element among its [children].
+
+#constraint valid (3.X.6)
+
+ ag-props-correct.2 = ag-props-correct.2: Error for attribute group ''{0}''. Duplicate attribute uses with the same name and target namespace are specified. Name of duplicate attribute use is ''{1}''.
+ ag-props-correct.3 = ag-props-correct.3: Error for attribute group ''{0}''. Two attribute declarations, ''{1}'' and ''{2}'' have types which are derived from ID.
+ a-props-correct.2 = a-props-correct.2: Invalid value constraint value ''{1}'' in attribute ''{0}''.
+ a-props-correct.3 = a-props-correct.3: Attribute ''{0}'' cannot use ''fixed'' or ''default'', because the attribute''s '{'type definition'}' is ID, or is derived from ID.
+ au-props-correct.2 = au-props-correct.2: In the attribute declaration of ''{0}'', a fixed value of ''{1}'' was specified. So if the attribute use referring to ''{0}'' also has a '{'value constraint'}', it must be fixed and its value must be ''{1}''.
+ cos-all-limited.1.2 = cos-all-limited.1.2: An 'all' model group must appear in a particle with '{'min occurs'}' = '{'max occurs'}' = 1, and that particle must be part of a pair which constitutes the '{'content type'}' of a complex type definition.
+ cos-all-limited.2 = cos-all-limited.2: The '{'max occurs'}' of an element in an ''all'' model group must be 0 or 1. The value ''{0}'' for element ''{1}'' is invalid.
+ cos-applicable-facets = cos-applicable-facets: Facet ''{0}'' is not allowed by type {1}.
+ cos-ct-extends.1.1 = cos-ct-extends.1.1: Type ''{0}'' was derived by extension from type ''{1}''. However, the ''final'' attribute of ''{1}'' forbids derivation by extension.
+ cos-ct-extends.1.4.3.2.2.1.a = cos-ct-extends.1.4.3.2.2.1.a: The content type of a derived type and that of its base must both be mixed or both be element-only. Type ''{0}'' is element only, but its base type is not.
+ cos-ct-extends.1.4.3.2.2.1.b = cos-ct-extends.1.4.3.2.2.1.b: The content type of a derived type and that of its base must both be mixed or both be element-only. Type ''{0}'' is mixed, but its base type is not.
+ cos-element-consistent = cos-element-consistent: Error for type ''{0}''. Multiple elements with name ''{1}'', with different types, appear in the model group.
+ cos-list-of-atomic = cos-list-of-atomic: In the definition of list type ''{0}'', type ''{1}'' is an invalid list element type because it is not atomic (''{1}'' is either a list type, or a union type which contains a list).
+ cos-nonambig = cos-nonambig: {0} and {1} (or elements from their substitution group) violate \"Unique Particle Attribution\". During validation against this schema, ambiguity would be created for those two particles.
+ cos-particle-restrict.a = cos-particle-restrict.a: Derived particle is empty, and base is not emptiable.
+ cos-particle-restrict.b = cos-particle-restrict.b: Base particle is empty, but derived particle is not.
+ cos-particle-restrict.2 = cos-particle-restrict.2: Forbidden particle restriction: ''{0}''.
+ cos-st-restricts.1.1 = cos-st-restricts.1.1: The type ''{1}'' is atomic, so its '{'base type definition'}', ''{0}'', must be an atomic simple type definition or a built-in primitive datatype.
+ cos-st-restricts.2.1 = cos-st-restricts.2.1: In the definition of list type ''{0}'', type ''{1}'' is an invalid item type because it is either a list type, or a union type that contains a list.
+ cos-st-restricts.2.3.1.1 = cos-st-restricts.2.3.1.1: The '{'final'}' component of the '{'item type definition'}', ''{0}'', contains ''list''. This means that ''{0}'' cannot be used as an item type for list type ''{1}''.
+ cos-st-restricts.3.3.1.1 = cos-st-restricts.3.3.1.1: The '{'final'}' component of the '{'member type definitions'}', ''{0}'', contains ''union''. This means that ''{0}'' cannot be used as an member type for union type ''{1}''.
+ cos-valid-default.2.1 = cos-valid-default.2.1: Element ''{0}'' has a value constraint and must have a mixed or simple content model.
+ cos-valid-default.2.2.2 = cos-valid-default.2.2.2: Since element ''{0}'' has a '{'value constraint'}' and its type definition has mixed '{'content type'}', then the particle of the '{'content type'}' must be emptiable.
+ c-props-correct.2 = c-props-correct.2: Cardinality of Fields for keyref ''{0}'' and key ''{1}'' must match each other.
+ ct-props-correct.3 = ct-props-correct.3: Circular definitions detected for complex type ''{0}''. This means that ''{0}'' is contained in its own type hierarchy, which is an error.
+ ct-props-correct.4 = ct-props-correct.4: Error for type ''{0}''. Duplicate attribute uses with the same name and target namespace are specified. Name of duplicate attribute use is ''{1}''.
+ ct-props-correct.5 = ct-props-correct.5: Error for type ''{0}''. Two attribute declarations, ''{1}'' and ''{2}'' have types which are derived from ID.
+ derivation-ok-restriction.1 = derivation-ok-restriction.1: Type ''{0}'' was derived by restriction from type ''{1}''. However, ''{1}'' has a '{'final'}' property that forbids derivation by restriction.
+ derivation-ok-restriction.2.1.1 = derivation-ok-restriction.2.1.1: Error for type ''{0}''. The attribute use ''{1}'' in this type has a ''use'' value of ''{2}'', which is inconsistent with the value of ''required'' in a matching attribute use in the base type.
+ derivation-ok-restriction.2.1.2 = derivation-ok-restriction.2.1.2: Error for type ''{0}''. The attribute use ''{1}'' in this type has type ''{2}'', which is not validly derived from ''{3}'', the type of the matching attribute use in the base type.
+ derivation-ok-restriction.2.1.3.a = derivation-ok-restriction.2.1.3.a: Error for type ''{0}''. The attribute use ''{1}'' in this type has an effective value constraint which is not fixed, and the effective value constraint of the matching attribute use in the base type is fixed.
+ derivation-ok-restriction.2.1.3.b = derivation-ok-restriction.2.1.3.b: Error for type ''{0}''. The attribute use ''{1}'' in this type has an effective value constraint fixed with a value of ''{2}'', which is not consistent with the value of ''{3}'' for the fixed effective value constraint of the matching attribute use in the base type.
+ derivation-ok-restriction.2.2.a = derivation-ok-restriction.2.2.a: Error for type ''{0}''. The attribute use ''{1}'' in this type does not have a matching attribute use in the base, and the base type does not have a wildcard attribute.
+ derivation-ok-restriction.2.2.b = derivation-ok-restriction.2.2.b: Error for type ''{0}''. The attribute use ''{1}'' in this type does not have a matching attribute use in the base, and the wildcard in the base type does not allow the namespace ''{2}'' of this attribute use.
+ derivation-ok-restriction.3 = derivation-ok-restriction.3: Error for type ''{0}''. The attribute use ''{1}'' in the base type has REQUIRED as true, but there is no matching attribute use in the derived type.
+ derivation-ok-restriction.4.1 = derivation-ok-restriction.4.1: Error for type ''{0}''. The derivation has an attribute wildcard, but the base does not have one.
+ derivation-ok-restriction.4.2 = derivation-ok-restriction.4.2: Error for type ''{0}''. The wildcard in the derivation is not a valid wildcard subset of the one in the base.
+ derivation-ok-restriction.4.3 = derivation-ok-restriction.4.3: Error for type ''{0}''. The process contents of the wildcard in the derivation ({1}) is weaker than that in the base ({2}).
+ derivation-ok-restriction.5.2.2.1 = derivation-ok-restriction.5.2.2.1: Error for type ''{0}''. The simple content type of this type, ''{1}'', is not a valid restriction of the simple content type of the base, ''{2}''.
+ derivation-ok-restriction.5.3.2 = derivation-ok-restriction.5.3.2: Error for type ''{0}''. The content type of this type is empty, but the content type of the base, ''{1}'', is not empty or emptiable.
+ derivation-ok-restriction.5.4.1.2 = derivation-ok-restriction.5.4.1.2: Error for type ''{0}''. The content type of this type is mixed, but the content type of the base, ''{1}'', is not.
+ derivation-ok-restriction.5.4.2 = derivation-ok-restriction.5.4.2: Error for type ''{0}''. The particle of the type is not a valid restriction of the particle of the base.
+ enumeration-required-notation = enumeration-required-notation: The NOTATION type, ''{0}'' used by {2} ''{1}'', must have an enumeration facet value which specifies the notation elements used by this type.
+ enumeration-valid-restriction = enumeration-valid-restriction: Enumeration value ''{0}'' is not in the value space of the base type, {1}.
+ e-props-correct.2 = e-props-correct.2: Invalid value constraint value ''{1}'' in element ''{0}''.
+ e-props-correct.4 = e-props-correct.4: The '{'type definition'}' of element ''{0}'' is not validly derived from the '{'type definition'}' of the substitutionHead ''{1}'', or the '{'substitution group exclusions'}' property of ''{1}'' does not allow this derivation.
+ e-props-correct.5 = e-props-correct.5: A '{'value constraint'}' must not be present on element ''{0}'', because the element''s '{'type definition'}' or '{'type definition'}'''s '{'content type'}' is ID, or is derived from ID.
+ e-props-correct.6 = e-props-correct.6: Circular substitution group detected for element ''{0}''.
+ fractionDigits-valid-restriction = fractionDigits-valid-restriction: In the definition of {2}, the value ''{0}'' for the facet ''fractionDigits'' is invalid, because it must be <= the value for ''fractionDigits'' which was set to ''{1}'' in one of the ancestor types.
+ fractionDigits-totalDigits = fractionDigits-totalDigits: In the definition of {2}, the value ''{0}'' for the facet ''fractionDigits'' is invalid, because the value must be <= the value for ''totalDigits'' which is ''{1}''.
+ length-minLength-maxLength.1.1 = length-minLength-maxLength.1.1: For type {0}, it is an error for the value of length ''{1}'' to be less than the value of minLength ''{2}''.
+ length-minLength-maxLength.1.2.a = length-minLength-maxLength.1.2.a: For type {0}, it is an error for the base to not have a minLength facet if the current restriction has the minLength facet and the current restriction or base has the length facet.
+ length-minLength-maxLength.1.2.b = length-minLength-maxLength.1.2.b: For type {0}, it is an error for the current minLength ''{1}'' to not equal the base minLength ''{2}''.
+ length-minLength-maxLength.2.1 = length-minLength-maxLength.2.1: For type {0}, it is an error for the value of length ''{1}'' to be greater than the value of maxLength ''{2}''.
+ length-minLength-maxLength.2.2.a = length-minLength-maxLength.2.2.a: For type {0}, it is an error for the base to not have a maxLength facet if the current restriction has the maxLength facet and the current restriction or base has the length facet.
+ length-minLength-maxLength.2.2.b = length-minLength-maxLength.2.2.b: For type {0}, it is an error for the current maxLength ''{1}'' to not equal the base maxLength ''{2}''.
+ length-valid-restriction = length-valid-restriction: Error for type ''{2}''. The value of length = ''{0}'' must be = the value of that of the base type ''{1}''.
+ maxExclusive-valid-restriction.1 = maxExclusive-valid-restriction.1: Error for type ''{2}''. The maxExclusive value =''{0}'' must be <= maxExclusive of the base type ''{1}''.
+ maxExclusive-valid-restriction.2 = maxExclusive-valid-restriction.2: Error for type ''{2}''. The maxExclusive value =''{0}'' must be <= maxInclusive of the base type ''{1}''.
+ maxExclusive-valid-restriction.3 = maxExclusive-valid-restriction.3: Error for type ''{2}''. The maxExclusive value =''{0}'' must be > minInclusive of the base type ''{1}''.
+ maxExclusive-valid-restriction.4 = maxExclusive-valid-restriction.4: Error for type ''{2}''. The maxExclusive value =''{0}'' must be > minExclusive of the base type ''{1}''.
+ maxInclusive-maxExclusive = maxInclusive-maxExclusive: It is an error for both maxInclusive and maxExclusive to be specified for the same datatype. In {2}, maxInclusive = ''{0}'' and maxExclusive = ''{1}''.
+ maxInclusive-valid-restriction.1 = maxInclusive-valid-restriction.1: Error for type ''{2}''. The maxInclusive value =''{0}'' must be <= maxInclusive of the base type ''{1}''.
+ maxInclusive-valid-restriction.2 = maxInclusive-valid-restriction.2: Error for type ''{2}''. The maxInclusive value =''{0}'' must be < maxExclusive of the base type ''{1}''.
+ maxInclusive-valid-restriction.3 = maxInclusive-valid-restriction.3: Error for type ''{2}''. The maxInclusive value =''{0}'' must be >= minInclusive of the base type ''{1}''.
+ maxInclusive-valid-restriction.4 = maxInclusive-valid-restriction.4: Error for type ''{2}''. The maxInclusive value =''{0}'' must be > minExclusive of the base type ''{1}''.
+ maxLength-valid-restriction = maxLength-valid-restriction: In the definition of {2}, maxLength value = ''{0}'' must be <= that of the base type ''{1}''.
+ mg-props-correct.2 = mg-props-correct.2: Circular definitions detected for group ''{0}''. Recursively following the '{'term'}' values of the particles leads to a particle whose '{'term'}' is the group itself.
+ minExclusive-less-than-equal-to-maxExclusive = minExclusive-less-than-equal-to-maxExclusive: In the definition of {2}, minExclusive value = ''{0}'' must be <= maxExclusive value = ''{1}''.
+ minExclusive-less-than-maxInclusive = minExclusive-less-than-maxInclusive: In the definition of {2}, minExclusive value = ''{0}'' must be < maxInclusive value = ''{1}''.
+ minExclusive-valid-restriction.1 = minExclusive-valid-restriction.1: Error for type ''{2}''. The minExclusive value =''{0}'' must be >= minExclusive of the base type ''{1}''.
+ minExclusive-valid-restriction.2 = minExclusive-valid-restriction.2: Error for type ''{2}''. The minExclusive value =''{0}'' must be <= maxInclusive of the base type ''{1}''.
+ minExclusive-valid-restriction.3 = minExclusive-valid-restriction.3: Error for type ''{2}''. The minExclusive value =''{0}'' must be >= minInclusive of the base type ''{1}''.
+ minExclusive-valid-restriction.4 = minExclusive-valid-restriction.4: Error for type ''{2}''. The minExclusive value =''{0}'' must be < maxExclusive of the base type ''{1}''.
+ minInclusive-less-than-equal-to-maxInclusive = minInclusive-less-than-equal-to-maxInclusive: In the definition of {2}, minInclusive value = ''{0}'' must be <= maxInclusive value = ''{1}''.
+ minInclusive-less-than-maxExclusive = minInclusive-less-than-maxExclusive: In the definition of {2}, minInclusive value = ''{0}'' must be < maxExclusive value = ''{1}''.
+ minInclusive-minExclusive = minInclusive-minExclusive: It is an error for both minInclusive and minExclusive to be specified for the same datatype. In {2}, minInclusive = ''{0}'' and minExclusive = ''{1}''.
+ minInclusive-valid-restriction.1 = minInclusive-valid-restriction.1: Error for type ''{2}''. The minInclusive value =''{0}'' must be >= minInclusive of the base type ''{1}''.
+ minInclusive-valid-restriction.2 = minInclusive-valid-restriction.2: Error for type ''{2}''. The minInclusive value =''{0}'' must be <= maxInclusive of the base type ''{1}''.
+ minInclusive-valid-restriction.3 = minInclusive-valid-restriction.3: Error for type ''{2}''. The minInclusive value =''{0}'' must be > minExclusive of the base type ''{1}''.
+ minInclusive-valid-restriction.4 = minInclusive-valid-restriction.4: Error for type ''{2}''. The minInclusive value =''{0}'' must be < maxExclusive of the base type ''{1}''.
+ minLength-less-than-equal-to-maxLength = minLength-less-than-equal-to-maxLength: In the definition of {2}, value of minLength = ''{0}'' must be < value of maxLength = ''{1}''.
+ minLength-valid-restriction = minLength-valid-restriction: In the definition of {2}, minLength = ''{0}'' must be >= than that of the base type, ''{1}''.
+ no-xmlns = no-xmlns: The {name} of an attribute declaration must not match 'xmlns'.
+ no-xsi = no-xsi: The '{'target namespace'}' of an attribute declaration must not match ''{0}''.
+ p-props-correct.2.1 = p-props-correct.2.1: In the declaration of ''{0}'', the value of ''minOccurs'' is ''{1}'', but it must not be greater than the value of ''maxOccurs'', which is ''{2}''.
+ rcase-MapAndSum.1 = rcase-MapAndSum.1: There is not a complete functional mapping between the particles.
+ rcase-MapAndSum.2 = rcase-MapAndSum.2: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}).
+ rcase-NameAndTypeOK.1 = rcase-NameAndTypeOK.1: Elements have names and target namespaces which are not the same: Element ''{0}'' in namespace ''{1}'' and element ''{2}'' in namespace ''{3}''.
+ rcase-NameAndTypeOK.2 = rcase-NameAndTypeOK.2: Error for the particle whose '{'term'}' is the element declaration ''{0}''. The element declaration''s '{'nillable'}' is true, but the corresponding particle in the base type has an element declaration whose '{'nillable'}' is false.
+ rcase-NameAndTypeOK.3 = rcase-NameAndTypeOK.3: Error for the particle whose '{'term'}' is the element declaration ''{0}''. Its occurrence range, ({1},{2}), is not a valid restriction of the range, ({3},{4}), of the corresponding particle in the base type.
+ rcase-NameAndTypeOK.4.a = rcase-NameAndTypeOK.4.a: Element ''{0}'' is not fixed, but the corresponding element in the base type is fixed with value ''{1}''.
+ rcase-NameAndTypeOK.4.b = rcase-NameAndTypeOK.4.b: Element ''{0}'' is fixed with value ''{1}'', but the corresponding element in the base type is fixed with value ''{2}''.
+ rcase-NameAndTypeOK.5 = rcase-NameAndTypeOK.5: Identity constraints for element ''{0}'' are not a subset of those in base.
+ rcase-NameAndTypeOK.6 = rcase-NameAndTypeOK.6: The disallowed substitutions for element ''{0}'' are not a superset of those in the base.
+ rcase-NameAndTypeOK.7 = rcase-NameAndTypeOK.7: The type of element ''{0}'', ''{1}'', is not derived from the type of the base element, ''{2}''.
+ rcase-NSCompat.1 = rcase-NSCompat.1: Element ''{0}'' has a namespace ''{1}'' which is not allowed by the wildcard in the base.
+ rcase-NSCompat.2 = rcase-NSCompat.2: Error for the particle whose '{'term'}' is the element declaration ''{0}''. Its occurrence range, ({1},{2}), is not a valid restriction of the range, ({3},{4}), of the corresponding particle in the base type.
+ rcase-NSRecurseCheckCardinality.1 = rcase-NSRecurseCheckCardinality.1: There is not a complete functional mapping between the particles.
+ rcase-NSRecurseCheckCardinality.2 = rcase-NSRecurseCheckCardinality.2: Group''s occurrence range, ({0},{1}), is not a valid restriction of base wildcard''s range, ({2},{3}).
+ rcase-NSSubset.1 = rcase-NSSubset.1: Wildcard is not a subset of corresponding wildcard in base.
+ rcase-NSSubset.2 = rcase-NSSubset.2: Wildcard''s occurrence range, ({0},{1}), is not a valid restriction of that in the base, ({2},{3}),.
+ rcase-NSSubset.3 = rcase-NSSubset.3: Wildcard''s process contents, ''{0}'', is weaker than that in the base, ''{1}''.
+ rcase-Recurse.1 = rcase-Recurse.1: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}).
+ rcase-Recurse.2 = rcase-Recurse.2: There is not a complete functional mapping between the particles.
+ rcase-RecurseLax.1 = rcase-RecurseLax.1: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}).
+ rcase-RecurseLax.2 = rcase-RecurseLax.2: There is not a complete functional mapping between the particles.
+ rcase-RecurseUnordered.1 = rcase-RecurseUnordered.1: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}).
+ rcase-RecurseUnordered.2 = rcase-RecurseUnordered.2: There is not a complete functional mapping between the particles.
+# We're using sch-props-correct.2 instead of the old src-redefine.1
+# src-redefine.1 = src-redefine.1: The component ''{0}'' is begin redefined, but its corresponding component isn't in the schema document being redefined (with namespace ''{2}''), but in a different document, with namespace ''{1}''.
+ sch-props-correct.2 = sch-props-correct.2: A schema cannot contain two global components with the same name; this schema contains two occurrences of ''{0}''.
+ st-props-correct.2 = st-props-correct.2: Circular definitions have been detected for simple type ''{0}''. This means that ''{0}'' is contained in its own type hierarchy, which is an error.
+ st-props-correct.3 = st-props-correct.3: Error for type ''{0}''. The value of '{'final'}' of the '{'base type definition'}', ''{1}'', forbids derivation by restriction.
+ totalDigits-valid-restriction = totalDigits-valid-restriction: In the definition of {2}, the value ''{0}'' for the facet ''totalDigits'' is invalid, because it must be <= the value for ''totalDigits'' which was set to ''{1}'' in one of the ancestor types.
+ whiteSpace-valid-restriction.1 = whiteSpace-valid-restriction.1: In the definition of {0}, the value ''{1}'' for the facet ''whitespace'' is invalid, because the value for ''whitespace'' has been set to ''collapse'' in one of the ancestor types.
+ whiteSpace-valid-restriction.2 = whiteSpace-valid-restriction.2: In the definition of {0}, the value ''preserve'' for the facet ''whitespace'' is invalid, because the value for ''whitespace'' has been set to ''replace'' in one of the ancestor types.
+
+#schema for Schemas
+
+ s4s-att-invalid-value = s4s-att-invalid-value: Invalid attribute value for ''{1}'' in element ''{0}''. Recorded reason: {2}
+ s4s-att-must-appear = s4s-att-must-appear: Attribute ''{1}'' must appear in element ''{0}''.
+ s4s-att-not-allowed = s4s-att-not-allowed: Attribute ''{1}'' cannot appear in element ''{0}''.
+ s4s-elt-invalid = s4s-elt-invalid: Element ''{0}'' is not a valid element in a schema document.
+ s4s-elt-must-match.1 = s4s-elt-must-match.1: The content of ''{0}'' must match {1}. A problem was found starting at: {2}.
+ s4s-elt-must-match.2 = s4s-elt-must-match.2: The content of ''{0}'' must match {1}. Not enough elements were found.
+ # the "invalid-content" messages provide less information than the "must-match" counterparts above. They're used for complex types when providing a "match" would be an information dump
+ s4s-elt-invalid-content.1 = s4s-elt-invalid-content.1: The content of ''{0}'' is invalid. Element ''{1}'' is invalid, misplaced, or occurs too often.
+ s4s-elt-invalid-content.2 = s4s-elt-invalid-content.2: The content of ''{0}'' is invalid. Element ''{1}'' cannot be empty.
+ s4s-elt-invalid-content.3 = s4s-elt-invalid-content.3: Elements of type ''{0}'' cannot appear after declarations as children of a element.
+ s4s-elt-schema-ns = s4s-elt-schema-ns: The namespace of element ''{0}'' must be from the schema namespace, ''http://www.w3.org/2001/XMLSchema''.
+ s4s-elt-character = s4s-elt-character: Non-whitespace characters are not allowed in schema elements other than ''xs:appinfo'' and ''xs:documentation''. Saw ''{0}''.
+
+# codes not defined by the spec
+
+ c-fields-xpaths = c-fields-xpaths: The field value = ''{0}'' is not valid.
+ c-general-xpath = c-general-xpath: The expression ''{0}'' is not valid with respect to the XPath subset supported by XML Schema.
+ c-general-xpath-ns = c-general-xpath-ns: A namespace prefix in XPath expression ''{0}'' was not bound to a namespace.
+ c-selector-xpath = c-selector-xpath: The selector value = ''{0}'' is not valid; selector xpaths cannot contain attributes.
+ EmptyTargetNamespace = EmptyTargetNamespace: In schema document ''{0}'', the value of the ''targetNamespace'' attribute cannot be an empty string.
+ FacetValueFromBase = FacetValueFromBase: In the declaration of type ''{0}'', value ''{1}'' of facet ''{2}'' must be from the value space of the base type, ''{3}''.
+ FixedFacetValue = FixedFacetValue: In the definition of {3}, the value ''{1}'' for the facet ''{0}'' is invalid, because the value for ''{0}'' has been set to ''{2}'' in one of the ancestor types, and '{'fixed'}' = true.
+ InvalidRegex = InvalidRegex: Pattern value ''{0}'' is not a valid regular expression. The reported error was: ''{1}''.
+ maxOccurLimit = Current configuration of the parser doesn''t allow the expansion of a content model for a complex type to contain more than {0} nodes.
+ PublicSystemOnNotation = PublicSystemOnNotation: At least one of 'public' and 'system' must appear in element 'notation'.
+ SchemaLocation = SchemaLocation: schemaLocation value = ''{0}'' must have even number of URI''s.
+ TargetNamespace.1 = TargetNamespace.1: Expecting namespace ''{0}'', but the target namespace of the schema document is ''{1}''.
+ TargetNamespace.2 = TargetNamespace.2: Expecting no namespace, but the schema document has a target namespace of ''{1}''.
+ UndeclaredEntity = UndeclaredEntity: Entity ''{0}'' is not declared.
+ UndeclaredPrefix = UndeclaredPrefix: Cannot resolve ''{0}'' as a QName: the prefix ''{1}'' is not declared.
+ FacetsContradict = FacetsContradict: For simpleType definition ''{2}'', the enumeration value ''{0}'' contradicts with value of ''{1}'' facet.
+
+# JAXP 1.2 schema source property errors
+
+ jaxp12-schema-source-type.1 = The ''http://java.sun.com/xml/jaxp/properties/schemaSource'' property cannot have a value of type ''{0}''. Possible types of the value supported are String, File, InputStream, InputSource or an array of these types.
+ jaxp12-schema-source-type.2 = The ''http://java.sun.com/xml/jaxp/properties/schemaSource'' property cannot have an array value of type ''{0}''. Possible types of the array supported are Object, String, File, InputStream and InputSource.
+ jaxp12-schema-source-ns = When using an array of Objects as the value of the 'http://java.sun.com/xml/jaxp/properties/schemaSource' property, it is illegal to have two schemas that share the same target namespace.
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/msg/XMLSerializerMessages.properties b/resources/xerces2-j-src/org/apache/xerces/impl/msg/XMLSerializerMessages.properties
new file mode 100644
index 0000000..e9e26cd
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/msg/XMLSerializerMessages.properties
@@ -0,0 +1,50 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores error messages for the Xerces XML
+# serializer. Many DOM Load/Save error messages also
+# live here, since the serializer largely implements that package.
+#
+# As usual with properties files, the messages are arranged in
+# key/value tuples.
+#
+# @version $Id$
+
+ BadMessageKey = The error message corresponding to the message key can not be found.
+ FormatFailed = An internal error occurred while formatting the following message:\n
+
+ ArgumentIsNull = Argument ''{0}'' is null.
+ NoWriterSupplied = No writer supplied for serializer.
+ MethodNotSupported = The method ''{0}'' is not supported by this factory.
+ ResetInMiddle = The serializer may not be reset in the middle of serialization.
+ Internal = Internal error: element state is zero.
+ NoName = There is no rawName and localName is null.
+ ElementQName = The element name ''{0}'' is not a QName.
+ ElementPrefix = Element ''{0}'' does not belong to any namespace: prefix could be undeclared or bound to some namespace.
+ AttributeQName = The attribute name ''{0}'' is not a QName.
+ AttributePrefix = Attribute ''{0}'' does not belong to any namespace: prefix could be undeclared or bound to some namespace.
+ InvalidNSDecl = Namespace declaration syntax is incorrect: {0}.
+ EndingCDATA = The character sequence \"]]>\" must not appear in content unless used to mark the end of a CDATA section.
+ SplittingCDATA = Splitting a CDATA section containing the CDATA section termination marker \"]]>\".
+ ResourceNotFound = The resource ''{0}'' could not be found.
+ ResourceNotLoaded = The resource ''{0}'' could not be loaded. {1}
+ SerializationStopped = Serialization stopped at user request.
+
+ # DOM Level 3 load and save messages
+ no-output-specified = no-output-specified: The output destination for data to be written to was null.
+ unsupported-encoding = unsupported-encoding: An unsupported encoding is encountered.
+ unable-to-serialize-node = unable-to-serialize-node: The node could not be serialized.
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/msg/XPointerMessages.properties b/resources/xerces2-j-src/org/apache/xerces/impl/msg/XPointerMessages.properties
new file mode 100644
index 0000000..038282b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/msg/XPointerMessages.properties
@@ -0,0 +1,44 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file stores localized messages for the Xerces XPointer implementation.
+#
+# The messages are arranged in key and value tuples in a ListResourceBundle.
+#
+# @version $Id$
+
+# Messages for message reporting
+BadMessageKey = The error message corresponding to the message key can not be found.
+FormatFailed = An internal error occurred while formatting the following message:\n
+
+# XPointer Framework Error Messages
+XPointerProcessingError = XPointerProcessingError: An error occurred while processing the XPointer expression.
+InvalidXPointerToken = InvalidXPointerToken: The XPointer expression contains the invalid token ''{0}''
+InvalidXPointerExpression = InvalidXPointerExpression: The XPointer expression ''{0}'' is invalid.
+MultipleShortHandPointers = MultipleShortHandPointers: The XPointer expression ''{0}'' is invalid. It has more than one ShortHand Pointer.
+SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: The XPointer expression ''{0}'' is invalid. The SchemeData was not followed by a '')'' character.
+SchemeUnsupported = SchemeUnsupported: The XPointer scheme ''{0}'' is not supported.
+InvalidShortHandPointer = InvalidShortHandPointer: The NCName of the ShortHand Pointer ''{0}'' is invalid.
+UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: The XPointer expression ''{0}'' is invalid. The number of open parenthesis ''{1}'' is not equal to the number of close parenthesis ''{2}''.
+InvalidSchemeDataInXPointer = InvalidSchemeDataInXPointer: The XPointer expression ''{0}'' contains invalid SchemeData.
+
+# XPointer Element Scheme Error Messages
+InvalidElementSchemeToken = InvalidElementSchemeToken: The element() scheme XPointer expression contains the invalid token ''{0}''
+InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: The Element Scheme XPointer expression ''{0}'' is invalid.
+XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: An error occurred while processing the XPointer element() Scheme expression.
+InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: The element() Scheme contains a ShortHand Pointer ''{0}'' with an invalid NCName.
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: The element() Scheme contains an invalid child sequence character ''{0}''.
\ No newline at end of file
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/validation/ConfigurableValidationState.java b/resources/xerces2-j-src/org/apache/xerces/impl/validation/ConfigurableValidationState.java
new file mode 100644
index 0000000..47c7fa6
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/validation/ConfigurableValidationState.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.validation;
+
+import java.util.Iterator;
+
+/**
+ * An extension of ValidationState which can be configured to turn
+ * off checking for ID/IDREF errors and unparsed entity errors.
+ *
+ * @xerces.internal
+ *
+ * @author Peter McCracken, IBM
+ * @version $Id$
+ */
+public final class ConfigurableValidationState extends ValidationState {
+
+ /**
+ * Whether to check for ID/IDREF errors
+ */
+ private boolean fIdIdrefChecking;
+
+ /**
+ * Whether to check for unparsed entity errors
+ */
+ private boolean fUnparsedEntityChecking;
+
+ /**
+ * Creates a new ConfigurableValidationState.
+ * By default, error checking for both ID/IDREFs
+ * and unparsed entities are turned on.
+ */
+ public ConfigurableValidationState() {
+ super();
+ fIdIdrefChecking = true;
+ fUnparsedEntityChecking = true;
+ }
+
+ /**
+ * Turns checking for ID/IDREF errors on and off.
+ * @param setting true to turn on error checking,
+ * false to turn off error checking
+ */
+ public void setIdIdrefChecking(boolean setting) {
+ fIdIdrefChecking = setting;
+ }
+
+ /**
+ * Turns checking for unparsed entity errors on and off.
+ * @param setting true to turn on error checking,
+ * false to turn off error checking
+ */
+ public void setUnparsedEntityChecking(boolean setting) {
+ fUnparsedEntityChecking = setting;
+ }
+
+ /**
+ * Checks if all IDREFs have a corresponding ID.
+ * @return null, if ID/IDREF checking is turned off
+ * otherwise, returns the value of the super implementation
+ */
+ public Iterator checkIDRefID() {
+ return (fIdIdrefChecking) ? super.checkIDRefID() : null;
+ }
+
+ /**
+ * Checks if an ID has already been declared.
+ * @return false, if ID/IDREF checking is turned off
+ * otherwise, returns the value of the super implementation
+ */
+ public boolean isIdDeclared(String name) {
+ return (fIdIdrefChecking) ? super.isIdDeclared(name) : false;
+ }
+
+ /**
+ * Checks if an entity is declared.
+ * @return true, if unparsed entity checking is turned off
+ * otherwise, returns the value of the super implementation
+ */
+ public boolean isEntityDeclared(String name) {
+ return (fUnparsedEntityChecking) ? super.isEntityDeclared(name) : true;
+ }
+
+ /**
+ * Checks if an entity is unparsed.
+ * @return true, if unparsed entity checking is turned off
+ * otherwise, returns the value of the super implementation
+ */
+ public boolean isEntityUnparsed(String name) {
+ return (fUnparsedEntityChecking) ? super.isEntityUnparsed(name) : true;
+ }
+
+ /**
+ * Adds the ID, if ID/IDREF checking is enabled.
+ * @param name the ID to add
+ */
+ public void addId(String name) {
+ if (fIdIdrefChecking) {
+ super.addId(name);
+ }
+ }
+
+ /**
+ * Adds the IDREF, if ID/IDREF checking is enabled.
+ * @param name the IDREF to add
+ */
+ public void addIdRef(String name) {
+ if (fIdIdrefChecking) {
+ super.addIdRef(name);
+ }
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/validation/EntityState.java b/resources/xerces2-j-src/org/apache/xerces/impl/validation/EntityState.java
new file mode 100644
index 0000000..db4a7ac
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/validation/EntityState.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.validation;
+
+
+/**
+ * The entity state interface defines methods that must be implemented
+ * by components that store information about entity declarations, as well as by
+ * entity validator that will need to validate attributes of type entity.
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani, IBM
+ * @version $Id$
+ */
+public interface EntityState {
+ /**
+ * Query method to check if entity with this name was declared.
+ *
+ * @param name
+ * @return true if name is a declared entity
+ */
+ public boolean isEntityDeclared (String name);
+
+ /**
+ * Query method to check if entity is unparsed.
+ *
+ * @param name
+ * @return true if name is an unparsed entity
+ */
+ public boolean isEntityUnparsed (String name);
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/validation/ValidationManager.java b/resources/xerces2-j-src/org/apache/xerces/impl/validation/ValidationManager.java
new file mode 100644
index 0000000..3ca1967
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/validation/ValidationManager.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.validation;
+
+import java.util.ArrayList;
+
+/**
+ * ValidationManager is a coordinator property for validators in the
+ * pipeline. Each validator must know how to interact with
+ * this property. Validators are not required to know what kind of
+ * other validators present in the pipeline, but should understand
+ * that there are others and that some coordination is required.
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani, IBM
+ * @version $Id$
+ */
+public class ValidationManager {
+
+ protected final ArrayList fVSs = new ArrayList();
+ protected boolean fGrammarFound = false;
+
+ // used by the DTD validator to tell other components that it has a
+ // cached DTD in hand so there's no reason to
+ // scan external subset or entity decls.
+ protected boolean fCachedDTD = false;
+
+ /**
+ * Each validator should call this method to add its ValidationState into
+ * the validation manager.
+ */
+ public final void addValidationState(ValidationState vs) {
+ fVSs.add(vs);
+ }
+
+ /**
+ * Set the information required to validate entity values.
+ */
+ public final void setEntityState(EntityState state) {
+ for (int i = fVSs.size()-1; i >= 0; i--) {
+ ((ValidationState)fVSs.get(i)).setEntityState(state);
+ }
+ }
+
+ public final void setGrammarFound(boolean grammar){
+ fGrammarFound = grammar;
+ }
+
+ public final boolean isGrammarFound(){
+ return fGrammarFound;
+ }
+
+ public final void setCachedDTD(boolean cachedDTD) {
+ fCachedDTD = cachedDTD;
+ } // setCachedDTD(boolean)
+
+ public final boolean isCachedDTD() {
+ return fCachedDTD;
+ } // isCachedDTD(): boolean
+
+
+ public final void reset () {
+ fVSs.clear();
+ fGrammarFound = false;
+ fCachedDTD = false;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/validation/ValidationState.java b/resources/xerces2-j-src/org/apache/xerces/impl/validation/ValidationState.java
new file mode 100644
index 0000000..9baab0d
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/validation/ValidationState.java
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.validation;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+
+import org.apache.xerces.impl.dv.ValidationContext;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.xni.NamespaceContext;
+
+/**
+ * Implementation of the ValidationContext interface. Used to establish an
+ * environment for simple type validation.
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani, IBM
+ * @version $Id$
+ */
+public class ValidationState implements ValidationContext {
+
+ //
+ // private data
+ //
+ private boolean fExtraChecking = true;
+ private boolean fFacetChecking = true;
+ private boolean fNormalize = true;
+ private boolean fNamespaces = true;
+
+ private EntityState fEntityState = null;
+ private NamespaceContext fNamespaceContext = null;
+ private SymbolTable fSymbolTable = null;
+ private Locale fLocale = null;
+
+ //REVISIT: Should replace with a lighter structure.
+ private final HashMap fIdTable = new HashMap();
+ private final HashMap fIdRefTable = new HashMap();
+ private final static Object fNullValue = new Object();
+
+ //
+ // public methods
+ //
+ public void setExtraChecking(boolean newValue) {
+ fExtraChecking = newValue;
+ }
+
+ public void setFacetChecking(boolean newValue) {
+ fFacetChecking = newValue;
+ }
+
+ public void setNormalizationRequired (boolean newValue) {
+ fNormalize = newValue;
+ }
+
+ public void setUsingNamespaces (boolean newValue) {
+ fNamespaces = newValue;
+ }
+
+ public void setEntityState(EntityState state) {
+ fEntityState = state;
+ }
+
+ public void setNamespaceSupport(NamespaceContext namespace) {
+ fNamespaceContext = namespace;
+ }
+
+ public void setSymbolTable(SymbolTable sTable) {
+ fSymbolTable = sTable;
+ }
+
+ /**
+ * return null if all IDREF values have a corresponding ID value;
+ * otherwise return an iterator for all the IDREF values without
+ * a matching ID value.
+ */
+ public Iterator checkIDRefID() {
+ HashSet missingIDs = null;
+ Iterator iter = fIdRefTable.keySet().iterator();
+ String key;
+ while (iter.hasNext()) {
+ key = (String) iter.next();
+ if (!fIdTable.containsKey(key)) {
+ if (missingIDs == null) {
+ missingIDs = new HashSet();
+ }
+ missingIDs.add(key);
+ }
+ }
+ return (missingIDs != null) ? missingIDs.iterator() : null;
+ }
+
+ public void reset () {
+ fExtraChecking = true;
+ fFacetChecking = true;
+ fNamespaces = true;
+ fIdTable.clear();
+ fIdRefTable.clear();
+ fEntityState = null;
+ fNamespaceContext = null;
+ fSymbolTable = null;
+ }
+
+ /**
+ * The same validation state can be used to validate more than one (schema)
+ * validation roots. Entity/Namespace/Symbol are shared, but each validation
+ * root needs its own id/idref tables. So we need this method to reset only
+ * the two tables.
+ */
+ public void resetIDTables() {
+ fIdTable.clear();
+ fIdRefTable.clear();
+ }
+
+ //
+ // implementation of ValidationContext methods
+ //
+
+ // whether to do extra id/idref/entity checking
+ public boolean needExtraChecking() {
+ return fExtraChecking;
+ }
+
+ // whether to validate against facets
+ public boolean needFacetChecking() {
+ return fFacetChecking;
+ }
+
+ public boolean needToNormalize (){
+ return fNormalize;
+ }
+
+ public boolean useNamespaces() {
+ return fNamespaces;
+ }
+
+ // entity
+ public boolean isEntityDeclared (String name) {
+ if (fEntityState !=null) {
+ return fEntityState.isEntityDeclared(getSymbol(name));
+ }
+ return false;
+ }
+ public boolean isEntityUnparsed (String name) {
+ if (fEntityState !=null) {
+ return fEntityState.isEntityUnparsed(getSymbol(name));
+ }
+ return false;
+ }
+
+ // id
+ public boolean isIdDeclared(String name) {
+ return fIdTable.containsKey(name);
+ }
+ public void addId(String name) {
+ fIdTable.put(name, fNullValue);
+ }
+
+ // idref
+ public void addIdRef(String name) {
+ fIdRefTable.put(name, fNullValue);
+ }
+ // get symbols
+
+ public String getSymbol (String symbol) {
+ if (fSymbolTable != null)
+ return fSymbolTable.addSymbol(symbol);
+ // if there is no symbol table, we return java-internalized string,
+ // because symbol table strings are also java-internalzied.
+ // this guarantees that the returned string from this method can be
+ // compared by reference with other symbol table string. -SG
+ return symbol.intern();
+ }
+ // qname, notation
+ public String getURI(String prefix) {
+ if (fNamespaceContext !=null) {
+ return fNamespaceContext.getURI(prefix);
+ }
+ return null;
+ }
+
+ // Locale
+
+ public void setLocale(Locale locale) {
+ fLocale = locale;
+ }
+
+ public Locale getLocale() {
+ return fLocale;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xpath/XPath.java b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/XPath.java
new file mode 100644
index 0000000..e1f5835
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/XPath.java
@@ -0,0 +1,2023 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xpath;
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XMLChar;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.QName;
+
+/**
+ * Bare minimum XPath parser.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ * @version $Id$
+ */
+public class XPath {
+
+ //
+ // Constants
+ //
+
+ private static final boolean DEBUG_ALL = false;
+
+ private static final boolean DEBUG_XPATH_PARSE = DEBUG_ALL || false;
+
+ private static final boolean DEBUG_ANY = DEBUG_XPATH_PARSE;
+
+ //
+ // Data
+ //
+
+ /** Expression. */
+ protected final String fExpression;
+
+ /** Symbol table. */
+ protected final SymbolTable fSymbolTable;
+
+ /** Location paths. */
+ protected final LocationPath[] fLocationPaths;
+
+ //
+ // Constructors
+ //
+
+ /** Constructs an XPath object from the specified expression. */
+ public XPath(String xpath, SymbolTable symbolTable,
+ NamespaceContext context)
+ throws XPathException {
+ fExpression = xpath;
+ fSymbolTable = symbolTable;
+ fLocationPaths = parseExpression(context);
+ if (DEBUG_XPATH_PARSE) {
+ System.out.println(">>> "+fLocationPaths);
+ }
+ } // (String,SymbolTable,NamespaceContext)
+
+ //
+ // Public methods
+ //
+
+ /**
+ * Returns a representation of all location paths for this XPath.
+ * XPath = locationPath ( '|' locationPath)
+ */
+ public LocationPath[] getLocationPaths() {
+ LocationPath[] ret=new LocationPath[fLocationPaths.length];
+ for (int i=0;i0){
+ buf.append('|');
+ }
+ buf.append(fLocationPaths[i].toString());
+ }
+ return buf.toString();
+ } // toString():String
+
+ //
+ // Private methods
+ //
+
+ /**
+ * Used by the {@link #parseExpression(NamespaceContext)} method
+ * to verify the assumption.
+ *
+ * If b is false, this method throws XPathException
+ * to report the error.
+ */
+ private static void check( boolean b ) throws XPathException {
+ if(!b) throw new XPathException("c-general-xpath");
+ }
+
+ /**
+ * Used by the {@link #parseExpression(NamespaceContext)} method
+ * to build a {@link LocationPath} object from the accumulated
+ * {@link Step}s.
+ */
+ private LocationPath buildLocationPath( Vector stepsVector ) throws XPathException {
+ int size = stepsVector.size();
+ check(size!=0);
+ Step[] steps = new Step[size];
+ stepsVector.copyInto(steps);
+ stepsVector.removeAllElements();
+
+ return new LocationPath(steps);
+ }
+
+ /**
+ * This method is implemented by using the XPathExprScanner and
+ * examining the list of tokens that it returns.
+ */
+ private LocationPath[] parseExpression(final NamespaceContext context)
+ throws XPathException {
+
+ // tokens
+ final XPath.Tokens xtokens = new XPath.Tokens(fSymbolTable);
+
+ // scanner
+ XPath.Scanner scanner = new XPath.Scanner(fSymbolTable) {
+ protected void addToken(XPath.Tokens tokens, int token)
+ throws XPathException {
+ if (
+ token == XPath.Tokens.EXPRTOKEN_ATSIGN ||
+ token == XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME ||
+ token == XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH ||
+ token == XPath.Tokens.EXPRTOKEN_PERIOD ||
+ token == XPath.Tokens.EXPRTOKEN_NAMETEST_ANY ||
+ token == XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE ||
+ token == XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH ||
+ token == XPath.Tokens.EXPRTOKEN_OPERATOR_UNION ||
+ token == XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD ||
+ token == XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE ||
+ token == XPath.Tokens.EXPRTOKEN_DOUBLE_COLON
+ //
+ ) {
+ super.addToken(tokens, token);
+ return;
+ }
+ throw new XPathException("c-general-xpath");
+ }
+ };
+
+ int length = fExpression.length();
+
+ boolean success = scanner.scanExpr(fSymbolTable,
+ xtokens, fExpression, 0, length);
+ if(!success)
+ throw new XPathException("c-general-xpath");
+
+ //fTokens.dumpTokens();
+ Vector stepsVector = new Vector();
+ ArrayList locationPathsVector= new ArrayList();
+
+ // true when the next token should be 'Step' (as defined in
+ // the production rule [3] of XML Schema P1 section 3.11.6
+ // if false, we are expecting either '|' or '/'.
+ //
+ // this is to make sure we can detect a token list like
+ // 'abc' '/' '/' 'def' 'ghi'
+ boolean expectingStep = true;
+
+ while (xtokens.hasMore()) {
+ final int token = xtokens.nextToken();
+
+ switch (token) {
+ case XPath.Tokens.EXPRTOKEN_OPERATOR_UNION :{
+ check(!expectingStep);
+ locationPathsVector.add(buildLocationPath(stepsVector));
+ expectingStep=true;
+ break;
+ }
+ case XPath.Tokens.EXPRTOKEN_ATSIGN: {
+ check(expectingStep);
+ Step step = new Step(
+ new Axis(Axis.ATTRIBUTE),
+ parseNodeTest(xtokens.nextToken(),xtokens,context));
+ stepsVector.addElement(step);
+ expectingStep=false;
+ break;
+ }
+ case XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE: {
+ check(expectingStep);
+ // If we got here we're expecting attribute::
+ if (xtokens.nextToken() != XPath.Tokens.EXPRTOKEN_DOUBLE_COLON) {
+ throw new XPathException("c-general-xpath");
+ }
+ Step step = new Step(
+ new Axis(Axis.ATTRIBUTE),
+ parseNodeTest(xtokens.nextToken(),xtokens,context));
+ stepsVector.addElement(step);
+ expectingStep = false;
+ break;
+ }
+ case XPath.Tokens.EXPRTOKEN_NAMETEST_ANY:
+ case XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE:
+ case XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME: {
+ check(expectingStep);
+ Step step = new Step(
+ new Axis(Axis.CHILD),
+ parseNodeTest(token,xtokens,context));
+ stepsVector.addElement(step);
+ expectingStep=false;
+ break;
+ }
+ case XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD: {
+ check(expectingStep);
+ // If we got here we're expecting child::
+ if (xtokens.nextToken() != XPath.Tokens.EXPRTOKEN_DOUBLE_COLON) {
+ throw new XPathException("c-general-xpath");
+ }
+ Step step = new Step(
+ new Axis(Axis.CHILD),
+ parseNodeTest(xtokens.nextToken(),xtokens,context));
+ stepsVector.addElement(step);
+ expectingStep = false;
+ break;
+ }
+ case XPath.Tokens.EXPRTOKEN_PERIOD: {
+ check(expectingStep);
+ expectingStep=false;
+
+ // unless this is the first step in this location path,
+ // there's really no reason to keep them in LocationPath.
+ // This amounts to shorten "a/././b/./c" to "a/b/c".
+ // Also, the matcher fails to work correctly if XPath
+ // has those redundant dots.
+ if (stepsVector.size()==0) {
+ // build step
+ Axis axis = new Axis(Axis.SELF);
+ NodeTest nodeTest = new NodeTest(NodeTest.NODE);
+ Step step = new Step(axis, nodeTest);
+ stepsVector.addElement(step);
+
+ if( xtokens.hasMore()
+ && xtokens.peekToken() == XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH){
+ // consume '//'
+ xtokens.nextToken();
+
+ // build step
+ axis = new Axis(Axis.DESCENDANT);
+ nodeTest = new NodeTest(NodeTest.NODE);
+ step = new Step(axis, nodeTest);
+ stepsVector.addElement(step);
+ expectingStep=true;
+ }
+ }
+ break;
+ }
+ case XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH:{
+ // this cannot appear in an arbitrary position.
+ // it is only allowed right after '.' when
+ // '.' is the first token of a location path.
+ throw new XPathException("c-general-xpath");
+ }
+ case XPath.Tokens.EXPRTOKEN_DOUBLE_COLON: {
+ // :: cannot appear in an arbitrary position.
+ // We only expect this token if the xpath
+ // contains child:: or attribute::
+ throw new XPathException("c-general-xpath");
+ }
+ case XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH: {
+ check(!expectingStep);
+ expectingStep=true;
+ break;
+ }
+ default:
+ // we should have covered all the tokens that we can possibly see.
+ throw new InternalError();
+ }
+ }
+
+ check(!expectingStep);
+
+ locationPathsVector.add(buildLocationPath(stepsVector));
+
+ // return location path
+ return (LocationPath[])locationPathsVector.toArray(new LocationPath[locationPathsVector.size()]);
+
+ } // parseExpression(SymbolTable,NamespaceContext)
+
+ /**
+ * Used by {@link #parseExpression} to parse a node test
+ * from the token list.
+ */
+ private NodeTest parseNodeTest( int typeToken, Tokens xtokens, NamespaceContext context )
+ throws XPathException {
+ switch(typeToken) {
+ case XPath.Tokens.EXPRTOKEN_NAMETEST_ANY:
+ return new NodeTest(NodeTest.WILDCARD);
+
+ case XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE:
+ case XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME:
+ // consume QName token
+ String prefix = xtokens.nextTokenAsString();
+ String uri = null;
+ if (context != null && prefix != XMLSymbols.EMPTY_STRING) {
+ uri = context.getURI(prefix);
+ }
+ if (prefix != XMLSymbols.EMPTY_STRING && context != null && uri == null) {
+ throw new XPathException("c-general-xpath-ns");
+ }
+
+ if (typeToken==XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE)
+ return new NodeTest(prefix,uri);
+
+ String localpart = xtokens.nextTokenAsString();
+ String rawname = prefix != XMLSymbols.EMPTY_STRING
+ ? fSymbolTable.addSymbol(prefix+':'+localpart)
+ : localpart;
+
+ return new NodeTest(new QName(prefix, localpart, rawname, uri));
+
+ default:
+ throw new XPathException("c-general-xpath");
+ }
+ }
+
+
+ //
+ // Classes
+ //
+
+ // location path information
+
+ /**
+ * A location path representation for an XPath expression.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ */
+ public static class LocationPath
+ implements Cloneable {
+
+ //
+ // Data
+ //
+
+ /** List of steps. */
+ public final Step[] steps;
+
+ //
+ // Constructors
+ //
+
+ /** Creates a location path from a series of steps. */
+ public LocationPath(Step[] steps) {
+ this.steps = steps;
+ } // (Step[])
+
+ /** Copy constructor. */
+ protected LocationPath(LocationPath path) {
+ steps = new Step[path.steps.length];
+ for (int i = 0; i < steps.length; i++) {
+ steps[i] = (Step)path.steps[i].clone();
+ }
+ } // (LocationPath)
+
+ //
+ // Object methods
+ //
+
+ /** Returns a string representation of this object. */
+ public String toString() {
+ StringBuffer str = new StringBuffer();
+ for (int i = 0; i < steps.length; i++) {
+ if (i > 0 && (steps[i-1].axis.type!=Axis.DESCENDANT
+ && steps[i].axis.type!=Axis.DESCENDANT) ){
+ str.append('/');
+ }
+ str.append(steps[i].toString());
+ }
+ // DEBUG: This code is just for debugging and should *not*
+ // be left in because it will mess up hashcodes of
+ // serialized versions of this object. -Ac
+ if (false) {
+ str.append('[');
+ String s = super.toString();
+ str.append(s.substring(s.indexOf('@')));
+ str.append(']');
+ }
+ return str.toString();
+ } // toString():String
+
+ /** Returns a clone of this object. */
+ public Object clone() {
+ return new LocationPath(this);
+ } // clone():Object
+
+ } // class locationPath
+
+ /**
+ * A location path step comprised of an axis and node test.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ */
+ public static class Step
+ implements Cloneable {
+
+ //
+ // Data
+ //
+
+ /** Axis. */
+ public final Axis axis;
+
+ /** Node test. */
+ public final NodeTest nodeTest;
+
+ //
+ // Constructors
+ //
+
+ /** Constructs a step from an axis and node test. */
+ public Step(Axis axis, NodeTest nodeTest) {
+ this.axis = axis;
+ this.nodeTest = nodeTest;
+ } // (Axis,NodeTest)
+
+ /** Copy constructor. */
+ protected Step(Step step) {
+ axis = (Axis)step.axis.clone();
+ nodeTest = (NodeTest)step.nodeTest.clone();
+ } // (Step)
+
+ //
+ // Object methods
+ //
+
+ /** Returns a string representation of this object. */
+ public String toString() {
+ if (axis.type == Axis.SELF) {
+ return ".";
+ }
+ if (axis.type == Axis.ATTRIBUTE) {
+ return "@" + nodeTest.toString();
+ }
+ if (axis.type == Axis.CHILD) {
+ return nodeTest.toString();
+ }
+ if (axis.type == Axis.DESCENDANT) {
+ return "//";
+ }
+ return "??? ("+axis.type+')';
+ } // toString():String
+
+ /** Returns a clone of this object. */
+ public Object clone() {
+ return new Step(this);
+ } // clone():Object
+
+ } // class Step
+
+ /**
+ * Axis.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ */
+ public static class Axis
+ implements Cloneable {
+
+ //
+ // Constants
+ //
+
+ /** Type: child. */
+ public static final short CHILD = 1;
+
+ /** Type: attribute. */
+ public static final short ATTRIBUTE = 2;
+
+ /** Type: self. */
+ public static final short SELF = 3;
+
+
+ /** Type: descendant. */
+ public static final short DESCENDANT = 4;
+ //
+ // Data
+ //
+
+ /** Axis type. */
+ public final short type;
+
+ //
+ // Constructors
+ //
+
+ /** Constructs an axis with the specified type. */
+ public Axis(short type) {
+ this.type = type;
+ } // (short)
+
+ /** Copy constructor. */
+ protected Axis(Axis axis) {
+ type = axis.type;
+ } // (Axis)
+
+ //
+ // Object methods
+ //
+
+ /** Returns a string representation of this object. */
+ public String toString() {
+ switch (type) {
+ case CHILD: return "child";
+ case ATTRIBUTE: return "attribute";
+ case SELF: return "self";
+ case DESCENDANT: return "descendant";
+ }
+ return "???";
+ } // toString():String
+
+ /** Returns a clone of this object. */
+ public Object clone() {
+ return new Axis(this);
+ } // clone():Object
+
+ } // class Axis
+
+ /**
+ * Node test.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ */
+ public static class NodeTest
+ implements Cloneable {
+
+ //
+ // Constants
+ //
+
+ /** Type: qualified name. */
+ public static final short QNAME = 1;
+
+ /** Type: wildcard. */
+ public static final short WILDCARD = 2;
+
+ /** Type: node. */
+ public static final short NODE = 3;
+
+ /** Type: namespace */
+ public static final short NAMESPACE= 4;
+
+ //
+ // Data
+ //
+
+ /** Node test type. */
+ public final short type;
+
+ /** Node qualified name. */
+ public final QName name = new QName();
+
+ //
+ // Constructors
+ //
+
+ /** Constructs a node test of type WILDCARD or NODE. */
+ public NodeTest(short type) {
+ this.type = type;
+ } // (int)
+
+ /** Constructs a node test of type QName. */
+ public NodeTest(QName name) {
+ this.type = QNAME;
+ this.name.setValues(name);
+ } // (QName)
+ /** Constructs a node test of type Namespace. */
+ public NodeTest(String prefix, String uri) {
+ this.type = NAMESPACE;
+ this.name.setValues(prefix, null, null, uri);
+ } // (String,String)
+
+ /** Copy constructor. */
+ public NodeTest(NodeTest nodeTest) {
+ type = nodeTest.type;
+ name.setValues(nodeTest.name);
+ } // (NodeTest)
+
+ //
+ // Object methods
+ //
+
+ /** Returns a string representation of this object. */
+ public String toString() {
+
+ switch (type) {
+ case QNAME: {
+ if (name.prefix.length() !=0) {
+ if (name.uri != null) {
+ return name.prefix+':'+name.localpart;
+ }
+ return "{"+name.uri+'}'+name.prefix+':'+name.localpart;
+ }
+ return name.localpart;
+ }
+ case NAMESPACE: {
+ if (name.prefix.length() !=0) {
+ if (name.uri != null) {
+ return name.prefix+":*";
+ }
+ return "{"+name.uri+'}'+name.prefix+":*";
+ }
+ return "???:*";
+ }
+ case WILDCARD: {
+ return "*";
+ }
+ case NODE: {
+ return "node()";
+ }
+ }
+ return "???";
+
+ } // toString():String
+
+ /** Returns a clone of this object. */
+ public Object clone() {
+ return new NodeTest(this);
+ } // clone():Object
+
+ } // class NodeTest
+
+ // xpath implementation
+
+ // NOTE: The XPath implementation classes are kept internal because
+ // this implementation is just a temporary hack until a better
+ // and/or more appropriate implementation can be written.
+ // keeping the code in separate source files would "muddy" the
+ // CVS directory when it's not needed. -Ac
+
+ /**
+ * List of tokens.
+ *
+ * @xerces.internal
+ *
+ * @author Glenn Marcy, IBM
+ * @author Andy Clark, IBM
+ *
+ * @version $Id$
+ */
+ private static final class Tokens {
+
+ static final boolean DUMP_TOKENS = false;
+
+ /**
+ * [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::'
+ * | NameTest | NodeType | Operator | FunctionName
+ * | AxisName | Literal | Number | VariableReference
+ */
+ public static final int
+ EXPRTOKEN_OPEN_PAREN = 0,
+ EXPRTOKEN_CLOSE_PAREN = 1,
+ EXPRTOKEN_OPEN_BRACKET = 2,
+ EXPRTOKEN_CLOSE_BRACKET = 3,
+ EXPRTOKEN_PERIOD = 4,
+ EXPRTOKEN_DOUBLE_PERIOD = 5,
+ EXPRTOKEN_ATSIGN = 6,
+ EXPRTOKEN_COMMA = 7,
+ EXPRTOKEN_DOUBLE_COLON = 8,
+ //
+ // [37] NameTest ::= '*' | NCName ':' '*' | QName
+ //
+ // followed by symbol handle of NCName or QName
+ //
+ EXPRTOKEN_NAMETEST_ANY = 9,
+ EXPRTOKEN_NAMETEST_NAMESPACE = 10,
+ EXPRTOKEN_NAMETEST_QNAME = 11,
+ //
+ // [38] NodeType ::= 'comment' | 'text' | 'processing-instruction' | 'node'
+ //
+ EXPRTOKEN_NODETYPE_COMMENT = 12,
+ EXPRTOKEN_NODETYPE_TEXT = 13,
+ EXPRTOKEN_NODETYPE_PI = 14,
+ EXPRTOKEN_NODETYPE_NODE = 15,
+ //
+ // [32] Operator ::= OperatorName
+ // | MultiplyOperator
+ // | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>='
+ // [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div'
+ // [34] MultiplyOperator ::= '*'
+ //
+ EXPRTOKEN_OPERATOR_AND = 16,
+ EXPRTOKEN_OPERATOR_OR = 17,
+ EXPRTOKEN_OPERATOR_MOD = 18,
+ EXPRTOKEN_OPERATOR_DIV = 19,
+ EXPRTOKEN_OPERATOR_MULT = 20,
+ EXPRTOKEN_OPERATOR_SLASH = 21,
+ EXPRTOKEN_OPERATOR_DOUBLE_SLASH = 22,
+ EXPRTOKEN_OPERATOR_UNION = 23,
+ EXPRTOKEN_OPERATOR_PLUS = 24,
+ EXPRTOKEN_OPERATOR_MINUS = 25,
+ EXPRTOKEN_OPERATOR_EQUAL = 26,
+ EXPRTOKEN_OPERATOR_NOT_EQUAL = 27,
+ EXPRTOKEN_OPERATOR_LESS = 28,
+ EXPRTOKEN_OPERATOR_LESS_EQUAL = 29,
+ EXPRTOKEN_OPERATOR_GREATER = 30,
+ EXPRTOKEN_OPERATOR_GREATER_EQUAL = 31,
+
+ //EXPRTOKEN_FIRST_OPERATOR = EXPRTOKEN_OPERATOR_AND,
+ //EXPRTOKEN_LAST_OPERATOR = EXPRTOKEN_OPERATOR_GREATER_EQUAL,
+
+ //
+ // [35] FunctionName ::= QName - NodeType
+ //
+ // followed by symbol handle
+ //
+ EXPRTOKEN_FUNCTION_NAME = 32,
+ //
+ // [6] AxisName ::= 'ancestor' | 'ancestor-or-self'
+ // | 'attribute'
+ // | 'child'
+ // | 'descendant' | 'descendant-or-self'
+ // | 'following' | 'following-sibling'
+ // | 'namespace'
+ // | 'parent'
+ // | 'preceding' | 'preceding-sibling'
+ // | 'self'
+ //
+ EXPRTOKEN_AXISNAME_ANCESTOR = 33,
+ EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF = 34,
+ EXPRTOKEN_AXISNAME_ATTRIBUTE = 35,
+ EXPRTOKEN_AXISNAME_CHILD = 36,
+ EXPRTOKEN_AXISNAME_DESCENDANT = 37,
+ EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF = 38,
+ EXPRTOKEN_AXISNAME_FOLLOWING = 39,
+ EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING = 40,
+ EXPRTOKEN_AXISNAME_NAMESPACE = 41,
+ EXPRTOKEN_AXISNAME_PARENT = 42,
+ EXPRTOKEN_AXISNAME_PRECEDING = 43,
+ EXPRTOKEN_AXISNAME_PRECEDING_SIBLING = 44,
+ EXPRTOKEN_AXISNAME_SELF = 45,
+ //
+ // [29] Literal ::= '"' [^"]* '"' | "'" [^']* "'"
+ //
+ // followed by symbol handle for literal
+ //
+ EXPRTOKEN_LITERAL = 46,
+ //
+ // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
+ // [31] Digits ::= [0-9]+
+ //
+ // followed by number handle
+ //
+ EXPRTOKEN_NUMBER = 47,
+ //
+ // [36] VariableReference ::= '$' QName
+ //
+ // followed by symbol handle for QName
+ //
+ EXPRTOKEN_VARIABLE_REFERENCE = 48;
+
+ private static final String[] fgTokenNames = {
+ "EXPRTOKEN_OPEN_PAREN",
+ "EXPRTOKEN_CLOSE_PAREN",
+ "EXPRTOKEN_OPEN_BRACKET",
+ "EXPRTOKEN_CLOSE_BRACKET",
+ "EXPRTOKEN_PERIOD",
+ "EXPRTOKEN_DOUBLE_PERIOD",
+ "EXPRTOKEN_ATSIGN",
+ "EXPRTOKEN_COMMA",
+ "EXPRTOKEN_DOUBLE_COLON",
+ "EXPRTOKEN_NAMETEST_ANY",
+ "EXPRTOKEN_NAMETEST_NAMESPACE",
+ "EXPRTOKEN_NAMETEST_QNAME",
+ "EXPRTOKEN_NODETYPE_COMMENT",
+ "EXPRTOKEN_NODETYPE_TEXT",
+ "EXPRTOKEN_NODETYPE_PI",
+ "EXPRTOKEN_NODETYPE_NODE",
+ "EXPRTOKEN_OPERATOR_AND",
+ "EXPRTOKEN_OPERATOR_OR",
+ "EXPRTOKEN_OPERATOR_MOD",
+ "EXPRTOKEN_OPERATOR_DIV",
+ "EXPRTOKEN_OPERATOR_MULT",
+ "EXPRTOKEN_OPERATOR_SLASH",
+ "EXPRTOKEN_OPERATOR_DOUBLE_SLASH",
+ "EXPRTOKEN_OPERATOR_UNION",
+ "EXPRTOKEN_OPERATOR_PLUS",
+ "EXPRTOKEN_OPERATOR_MINUS",
+ "EXPRTOKEN_OPERATOR_EQUAL",
+ "EXPRTOKEN_OPERATOR_NOT_EQUAL",
+ "EXPRTOKEN_OPERATOR_LESS",
+ "EXPRTOKEN_OPERATOR_LESS_EQUAL",
+ "EXPRTOKEN_OPERATOR_GREATER",
+ "EXPRTOKEN_OPERATOR_GREATER_EQUAL",
+ "EXPRTOKEN_FUNCTION_NAME",
+ "EXPRTOKEN_AXISNAME_ANCESTOR",
+ "EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF",
+ "EXPRTOKEN_AXISNAME_ATTRIBUTE",
+ "EXPRTOKEN_AXISNAME_CHILD",
+ "EXPRTOKEN_AXISNAME_DESCENDANT",
+ "EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF",
+ "EXPRTOKEN_AXISNAME_FOLLOWING",
+ "EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING",
+ "EXPRTOKEN_AXISNAME_NAMESPACE",
+ "EXPRTOKEN_AXISNAME_PARENT",
+ "EXPRTOKEN_AXISNAME_PRECEDING",
+ "EXPRTOKEN_AXISNAME_PRECEDING_SIBLING",
+ "EXPRTOKEN_AXISNAME_SELF",
+ "EXPRTOKEN_LITERAL",
+ "EXPRTOKEN_NUMBER",
+ "EXPRTOKEN_VARIABLE_REFERENCE"
+ };
+
+ /**
+ *
+ */
+ private static final int INITIAL_TOKEN_COUNT = 1 << 8;
+ private int[] fTokens = new int[INITIAL_TOKEN_COUNT];
+ private int fTokenCount = 0; // for writing
+
+ private SymbolTable fSymbolTable;
+
+ // REVISIT: Code something better here. -Ac
+ private java.util.Hashtable fSymbolMapping = new java.util.Hashtable();
+
+ // REVISIT: Code something better here. -Ac
+ private java.util.Hashtable fTokenNames = new java.util.Hashtable();
+
+ /**
+ * Current position in the token list.
+ */
+ private int fCurrentTokenIndex;
+
+ //
+ // Constructors
+ //
+
+ public Tokens(SymbolTable symbolTable) {
+ fSymbolTable = symbolTable;
+ final String[] symbols = {
+ "ancestor", "ancestor-or-self", "attribute",
+ "child", "descendant", "descendant-or-self",
+ "following", "following-sibling", "namespace",
+ "parent", "preceding", "preceding-sibling",
+ "self",
+ };
+ for (int i = 0; i < symbols.length; i++) {
+ fSymbolMapping.put(fSymbolTable.addSymbol(symbols[i]), new Integer(i));
+ }
+ fTokenNames.put(new Integer(EXPRTOKEN_OPEN_PAREN), "EXPRTOKEN_OPEN_PAREN");
+ fTokenNames.put(new Integer(EXPRTOKEN_CLOSE_PAREN), "EXPRTOKEN_CLOSE_PAREN");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPEN_BRACKET), "EXPRTOKEN_OPEN_BRACKET");
+ fTokenNames.put(new Integer(EXPRTOKEN_CLOSE_BRACKET), "EXPRTOKEN_CLOSE_BRACKET");
+ fTokenNames.put(new Integer(EXPRTOKEN_PERIOD), "EXPRTOKEN_PERIOD");
+ fTokenNames.put(new Integer(EXPRTOKEN_DOUBLE_PERIOD), "EXPRTOKEN_DOUBLE_PERIOD");
+ fTokenNames.put(new Integer(EXPRTOKEN_ATSIGN), "EXPRTOKEN_ATSIGN");
+ fTokenNames.put(new Integer(EXPRTOKEN_COMMA), "EXPRTOKEN_COMMA");
+ fTokenNames.put(new Integer(EXPRTOKEN_DOUBLE_COLON), "EXPRTOKEN_DOUBLE_COLON");
+ fTokenNames.put(new Integer(EXPRTOKEN_NAMETEST_ANY), "EXPRTOKEN_NAMETEST_ANY");
+ fTokenNames.put(new Integer(EXPRTOKEN_NAMETEST_NAMESPACE), "EXPRTOKEN_NAMETEST_NAMESPACE");
+ fTokenNames.put(new Integer(EXPRTOKEN_NAMETEST_QNAME), "EXPRTOKEN_NAMETEST_QNAME");
+ fTokenNames.put(new Integer(EXPRTOKEN_NODETYPE_COMMENT), "EXPRTOKEN_NODETYPE_COMMENT");
+ fTokenNames.put(new Integer(EXPRTOKEN_NODETYPE_TEXT), "EXPRTOKEN_NODETYPE_TEXT");
+ fTokenNames.put(new Integer(EXPRTOKEN_NODETYPE_PI), "EXPRTOKEN_NODETYPE_PI");
+ fTokenNames.put(new Integer(EXPRTOKEN_NODETYPE_NODE), "EXPRTOKEN_NODETYPE_NODE");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_AND), "EXPRTOKEN_OPERATOR_AND");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_OR), "EXPRTOKEN_OPERATOR_OR");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_MOD), "EXPRTOKEN_OPERATOR_MOD");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_DIV), "EXPRTOKEN_OPERATOR_DIV");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_MULT), "EXPRTOKEN_OPERATOR_MULT");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_SLASH), "EXPRTOKEN_OPERATOR_SLASH");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_DOUBLE_SLASH), "EXPRTOKEN_OPERATOR_DOUBLE_SLASH");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_UNION), "EXPRTOKEN_OPERATOR_UNION");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_PLUS), "EXPRTOKEN_OPERATOR_PLUS");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_MINUS), "EXPRTOKEN_OPERATOR_MINUS");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_EQUAL), "EXPRTOKEN_OPERATOR_EQUAL");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_NOT_EQUAL), "EXPRTOKEN_OPERATOR_NOT_EQUAL");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_LESS), "EXPRTOKEN_OPERATOR_LESS");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_LESS_EQUAL), "EXPRTOKEN_OPERATOR_LESS_EQUAL");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_GREATER), "EXPRTOKEN_OPERATOR_GREATER");
+ fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_GREATER_EQUAL), "EXPRTOKEN_OPERATOR_GREATER_EQUAL");
+ fTokenNames.put(new Integer(EXPRTOKEN_FUNCTION_NAME), "EXPRTOKEN_FUNCTION_NAME");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_ANCESTOR), "EXPRTOKEN_AXISNAME_ANCESTOR");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF), "EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_ATTRIBUTE), "EXPRTOKEN_AXISNAME_ATTRIBUTE");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_CHILD), "EXPRTOKEN_AXISNAME_CHILD");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_DESCENDANT), "EXPRTOKEN_AXISNAME_DESCENDANT");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF), "EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_FOLLOWING), "EXPRTOKEN_AXISNAME_FOLLOWING");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING), "EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_NAMESPACE), "EXPRTOKEN_AXISNAME_NAMESPACE");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_PARENT), "EXPRTOKEN_AXISNAME_PARENT");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_PRECEDING), "EXPRTOKEN_AXISNAME_PRECEDING");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_PRECEDING_SIBLING), "EXPRTOKEN_AXISNAME_PRECEDING_SIBLING");
+ fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_SELF), "EXPRTOKEN_AXISNAME_SELF");
+ fTokenNames.put(new Integer(EXPRTOKEN_LITERAL), "EXPRTOKEN_LITERAL");
+ fTokenNames.put(new Integer(EXPRTOKEN_NUMBER), "EXPRTOKEN_NUMBER");
+ fTokenNames.put(new Integer(EXPRTOKEN_VARIABLE_REFERENCE), "EXPRTOKEN_VARIABLE_REFERENCE");
+ }
+
+ //
+ // Public methods
+ //
+
+// public String getTokenName(int token) {
+// if (token < 0 || token >= fgTokenNames.length)
+// return null;
+// return fgTokenNames[token];
+// }
+//
+ public String getTokenString(int token) {
+ return (String)fTokenNames.get(new Integer(token));
+ }
+
+ public void addToken(String tokenStr) {
+ Integer tokenInt = (Integer)fTokenNames.get(tokenStr);
+ if (tokenInt == null) {
+ tokenInt = new Integer(fTokenNames.size());
+ fTokenNames.put(tokenInt, tokenStr);
+ }
+ addToken(tokenInt.intValue());
+ }
+
+ public void addToken(int token) {
+ try {
+ fTokens[fTokenCount] = token;
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ int[] oldList = fTokens;
+ fTokens = new int[fTokenCount << 1];
+ System.arraycopy(oldList, 0, fTokens, 0, fTokenCount);
+ fTokens[fTokenCount] = token;
+ }
+ fTokenCount++;
+ }
+// public int getTokenCount() {
+// return fTokenCount;
+// }
+// public int getToken(int tokenIndex) {
+// return fTokens[tokenIndex];
+// }
+
+ /**
+ * Resets the current position to the head of the token list.
+ */
+ public void rewind() {
+ fCurrentTokenIndex=0;
+ }
+ /**
+ * Returns true if the {@link #getNextToken()} method
+ * returns a valid token.
+ */
+ public boolean hasMore() {
+ return fCurrentTokenIndexnew XPathException("c-general-xpath");.
+ */
+ public int nextToken() throws XPathException {
+ if( fCurrentTokenIndex==fTokenCount )
+ throw new XPathException("c-general-xpath");
+ return fTokens[fCurrentTokenIndex++];
+ }
+ /**
+ * Obtains the token at the current position, without advancing
+ * the current position.
+ *
+ * If there's no such next token, this method throws
+ * new XPathException("c-general-xpath");.
+ */
+ public int peekToken() throws XPathException {
+ if( fCurrentTokenIndex==fTokenCount )
+ throw new XPathException("c-general-xpath");
+ return fTokens[fCurrentTokenIndex];
+ }
+ /**
+ * Obtains the token at the current position as a String.
+ *
+ * If there's no current token or if the current token
+ * is not a string token, this method throws
+ * new XPathException("c-general-xpath");.
+ */
+ public String nextTokenAsString() throws XPathException {
+ String s = getTokenString(nextToken());
+ if(s==null) throw new XPathException("c-general-xpath");
+ return s;
+ }
+
+ public void dumpTokens() {
+ //if (DUMP_TOKENS) {
+ for (int i = 0; i < fTokenCount; i++) {
+ switch (fTokens[i]) {
+ case EXPRTOKEN_OPEN_PAREN:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_CLOSE_PAREN:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPEN_BRACKET:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_CLOSE_BRACKET:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_PERIOD:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_DOUBLE_PERIOD:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_ATSIGN:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_COMMA:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_DOUBLE_COLON:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_NAMETEST_ANY:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_NAMETEST_NAMESPACE:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_NAMETEST_QNAME:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_NODETYPE_COMMENT:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_NODETYPE_TEXT:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_NODETYPE_PI:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_NODETYPE_NODE:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_AND:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_OR:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_MOD:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_DIV:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_MULT:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_SLASH:
+ System.out.print("");
+ if (i + 1 < fTokenCount) {
+ System.out.println();
+ System.out.print(" ");
+ }
+ break;
+ case EXPRTOKEN_OPERATOR_DOUBLE_SLASH:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_UNION:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_PLUS:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_MINUS:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_EQUAL:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_NOT_EQUAL:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_LESS:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_LESS_EQUAL:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_GREATER:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_OPERATOR_GREATER_EQUAL:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_FUNCTION_NAME:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_ANCESTOR:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_ATTRIBUTE:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_CHILD:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_DESCENDANT:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_FOLLOWING:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_NAMESPACE:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_PARENT:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_PRECEDING:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_PRECEDING_SIBLING:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_AXISNAME_SELF:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_LITERAL:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_NUMBER:
+ System.out.print("");
+ break;
+ case EXPRTOKEN_VARIABLE_REFERENCE:
+ System.out.print("");
+ break;
+ default:
+ System.out.println("??/>");
+ }
+ }
+ System.out.println();
+ //}
+ }
+
+ } // class Tokens
+
+ /**
+ * @xerces.internal
+ *
+ * @author Glenn Marcy, IBM
+ * @author Andy Clark, IBM
+ *
+ * @version $Id$
+ */
+ private static class Scanner {
+
+ /**
+ * 7-bit ASCII subset
+ *
+ * 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ * 0, 0, 0, 0, 0, 0, 0, 0, 0, HT, LF, 0, 0, CR, 0, 0, // 0
+ * 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
+ * SP, !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, // 2
+ * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, :, ;, <, =, >, ?, // 3
+ * @, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, // 4
+ * P, Q, R, S, T, U, V, W, X, Y, Z, [, \, ], ^, _, // 5
+ * `, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, // 6
+ * p, q, r, s, t, u, v, w, x, y, z, {, |, }, ~, DEL // 7
+ */
+ private static final byte
+ CHARTYPE_INVALID = 0, // invalid XML character
+ CHARTYPE_OTHER = 1, // not special - one of "#%&;?\^`{}~" or DEL
+ CHARTYPE_WHITESPACE = 2, // one of "\t\n\r " (0x09, 0x0A, 0x0D, 0x20)
+ CHARTYPE_EXCLAMATION = 3, // '!' (0x21)
+ CHARTYPE_QUOTE = 4, // '\"' or '\'' (0x22 and 0x27)
+ CHARTYPE_DOLLAR = 5, // '$' (0x24)
+ CHARTYPE_OPEN_PAREN = 6, // '(' (0x28)
+ CHARTYPE_CLOSE_PAREN = 7, // ')' (0x29)
+ CHARTYPE_STAR = 8, // '*' (0x2A)
+ CHARTYPE_PLUS = 9, // '+' (0x2B)
+ CHARTYPE_COMMA = 10, // ',' (0x2C)
+ CHARTYPE_MINUS = 11, // '-' (0x2D)
+ CHARTYPE_PERIOD = 12, // '.' (0x2E)
+ CHARTYPE_SLASH = 13, // '/' (0x2F)
+ CHARTYPE_DIGIT = 14, // '0'-'9' (0x30 to 0x39)
+ CHARTYPE_COLON = 15, // ':' (0x3A)
+ CHARTYPE_LESS = 16, // '<' (0x3C)
+ CHARTYPE_EQUAL = 17, // '=' (0x3D)
+ CHARTYPE_GREATER = 18, // '>' (0x3E)
+ CHARTYPE_ATSIGN = 19, // '@' (0x40)
+ CHARTYPE_LETTER = 20, // 'A'-'Z' or 'a'-'z' (0x41 to 0x5A and 0x61 to 0x7A)
+ CHARTYPE_OPEN_BRACKET = 21, // '[' (0x5B)
+ CHARTYPE_CLOSE_BRACKET = 22, // ']' (0x5D)
+ CHARTYPE_UNDERSCORE = 23, // '_' (0x5F)
+ CHARTYPE_UNION = 24, // '|' (0x7C)
+ CHARTYPE_NONASCII = 25; // Non-ASCII Unicode codepoint (>= 0x80)
+
+ private static final byte[] fASCIICharMap = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 3, 4, 1, 5, 1, 1, 4, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 1, 16, 17, 18, 1,
+ 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 1, 22, 1, 23,
+ 1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1, 24, 1, 1, 1
+ };
+
+ /**
+ * Symbol literals
+ */
+
+ //
+ // Data
+ //
+
+ /** Symbol table. */
+ private SymbolTable fSymbolTable;
+
+ // symbols
+
+ private static final String fAndSymbol = "and".intern();
+ private static final String fOrSymbol = "or".intern();
+ private static final String fModSymbol = "mod".intern();
+ private static final String fDivSymbol = "div".intern();
+
+ private static final String fCommentSymbol = "comment".intern();
+ private static final String fTextSymbol = "text".intern();
+ private static final String fPISymbol = "processing-instruction".intern();
+ private static final String fNodeSymbol = "node".intern();
+
+ private static final String fAncestorSymbol = "ancestor".intern();
+ private static final String fAncestorOrSelfSymbol = "ancestor-or-self".intern();
+ private static final String fAttributeSymbol = "attribute".intern();
+ private static final String fChildSymbol = "child".intern();
+ private static final String fDescendantSymbol = "descendant".intern();
+ private static final String fDescendantOrSelfSymbol = "descendant-or-self".intern();
+ private static final String fFollowingSymbol = "following".intern();
+ private static final String fFollowingSiblingSymbol = "following-sibling".intern();
+ private static final String fNamespaceSymbol = "namespace".intern();
+ private static final String fParentSymbol = "parent".intern();
+ private static final String fPrecedingSymbol = "preceding".intern();
+ private static final String fPrecedingSiblingSymbol = "preceding-sibling".intern();
+ private static final String fSelfSymbol = "self".intern();
+
+ //
+ // Constructors
+ //
+
+ /** Constructs an XPath expression scanner. */
+ public Scanner(SymbolTable symbolTable) {
+
+ // save pool and tokens
+ fSymbolTable = symbolTable;
+
+ } // (SymbolTable)
+
+ /**
+ *
+ */
+ public boolean scanExpr(SymbolTable symbolTable,
+ XPath.Tokens tokens, String data,
+ int currentOffset, int endOffset)
+ throws XPathException {
+
+ int nameOffset;
+ String nameHandle, prefixHandle;
+ boolean starIsMultiplyOperator = false;
+ int ch;
+
+ while (true) {
+ if (currentOffset == endOffset) {
+ break;
+ }
+ ch = data.charAt(currentOffset);
+ //
+ // [39] ExprWhitespace ::= S
+ //
+ while (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D) {
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ ch = data.charAt(currentOffset);
+ }
+ if (currentOffset == endOffset) {
+ break;
+ }
+ //
+ // [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::'
+ // | NameTest | NodeType | Operator | FunctionName
+ // | AxisName | Literal | Number | VariableReference
+ //
+ byte chartype = (ch >= 0x80) ? CHARTYPE_NONASCII : fASCIICharMap[ch];
+ switch (chartype) {
+ case CHARTYPE_OPEN_PAREN: // '('
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPEN_PAREN);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ case CHARTYPE_CLOSE_PAREN: // ')'
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_CLOSE_PAREN);
+ starIsMultiplyOperator = true;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ case CHARTYPE_OPEN_BRACKET: // '['
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPEN_BRACKET);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ case CHARTYPE_CLOSE_BRACKET: // ']'
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_CLOSE_BRACKET);
+ starIsMultiplyOperator = true;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ //
+ // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
+ // ^^^^^^^^^^
+ //
+ case CHARTYPE_PERIOD: // '.', '..' or '.' Digits
+ if (currentOffset + 1 == endOffset) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD);
+ starIsMultiplyOperator = true;
+ currentOffset++;
+ break;
+ }
+ ch = data.charAt(currentOffset + 1);
+ if (ch == '.') { // '..'
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_DOUBLE_PERIOD);
+ starIsMultiplyOperator = true;
+ currentOffset += 2;
+ } else if (ch >= '0' && ch <= '9') {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_NUMBER);
+ starIsMultiplyOperator = true;
+ currentOffset = scanNumber(tokens, data, endOffset, currentOffset/*, encoding*/);
+ } else if (ch == '/') {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD);
+ starIsMultiplyOperator = true;
+ currentOffset++;
+ } else if (ch == '|') {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD);
+ starIsMultiplyOperator = true;
+ currentOffset++;
+ break;
+ } else if (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D) {
+ // this is legal if the next token is non-existent or |
+ do {
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ ch = data.charAt(currentOffset);
+ } while (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D);
+ if (currentOffset == endOffset || ch == '|') {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD);
+ starIsMultiplyOperator = true;
+ break;
+ }
+ throw new XPathException ("c-general-xpath");
+ } else { // '.'
+ throw new XPathException ("c-general-xpath");
+ }
+ if (currentOffset == endOffset) {
+ break;
+ }
+ break;
+ case CHARTYPE_ATSIGN: // '@'
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_ATSIGN);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ case CHARTYPE_COMMA: // ','
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_COMMA);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ case CHARTYPE_COLON: // '::'
+ if (++currentOffset == endOffset) {
+ // System.out.println("abort 1a");
+ return false; // REVISIT
+ }
+ ch = data.charAt(currentOffset);
+ if (ch != ':') {
+ // System.out.println("abort 1b");
+ return false; // REVISIT
+ }
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_DOUBLE_COLON);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ case CHARTYPE_SLASH: // '/' and '//'
+ if (++currentOffset == endOffset) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH);
+ starIsMultiplyOperator = false;
+ break;
+ }
+ ch = data.charAt(currentOffset);
+ if (ch == '/') { // '//'
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ } else {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH);
+ starIsMultiplyOperator = false;
+ }
+ break;
+ case CHARTYPE_UNION: // '|'
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_UNION);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ case CHARTYPE_PLUS: // '+'
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_PLUS);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ case CHARTYPE_MINUS: // '-'
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_MINUS);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ case CHARTYPE_EQUAL: // '='
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_EQUAL);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ case CHARTYPE_EXCLAMATION: // '!='
+ if (++currentOffset == endOffset) {
+ // System.out.println("abort 2a");
+ return false; // REVISIT
+ }
+ ch = data.charAt(currentOffset);
+ if (ch != '=') {
+ // System.out.println("abort 2b");
+ return false; // REVISIT
+ }
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_NOT_EQUAL);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ case CHARTYPE_LESS: // '<' and '<='
+ if (++currentOffset == endOffset) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_LESS);
+ starIsMultiplyOperator = false;
+ break;
+ }
+ ch = data.charAt(currentOffset);
+ if (ch == '=') { // '<='
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_LESS_EQUAL);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ } else {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_LESS);
+ starIsMultiplyOperator = false;
+ }
+ break;
+ case CHARTYPE_GREATER: // '>' and '>='
+ if (++currentOffset == endOffset) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_GREATER);
+ starIsMultiplyOperator = false;
+ break;
+ }
+ ch = data.charAt(currentOffset);
+ if (ch == '=') { // '>='
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_GREATER_EQUAL);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ } else {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_GREATER);
+ starIsMultiplyOperator = false;
+ }
+ break;
+ //
+ // [29] Literal ::= '"' [^"]* '"' | "'" [^']* "'"
+ //
+ case CHARTYPE_QUOTE: // '\"' or '\''
+ int qchar = ch;
+ if (++currentOffset == endOffset) {
+ // System.out.println("abort 2c");
+ return false; // REVISIT
+ }
+ ch = data.charAt(currentOffset);
+ int litOffset = currentOffset;
+ while (ch != qchar) {
+ if (++currentOffset == endOffset) {
+ // System.out.println("abort 2d");
+ return false; // REVISIT
+ }
+ ch = data.charAt(currentOffset);
+ }
+ int litLength = currentOffset - litOffset;
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_LITERAL);
+ starIsMultiplyOperator = true;
+ tokens.addToken(symbolTable.addSymbol(data.substring(litOffset, litOffset + litLength)));
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ //
+ // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
+ // [31] Digits ::= [0-9]+
+ //
+ case CHARTYPE_DIGIT:
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_NUMBER);
+ starIsMultiplyOperator = true;
+ currentOffset = scanNumber(tokens, data, endOffset, currentOffset/*, encoding*/);
+ break;
+ //
+ // [36] VariableReference ::= '$' QName
+ //
+ case CHARTYPE_DOLLAR:
+ if (++currentOffset == endOffset) {
+ // System.out.println("abort 3a");
+ return false; // REVISIT
+ }
+ nameOffset = currentOffset;
+ currentOffset = scanNCName(data, endOffset, currentOffset);
+ if (currentOffset == nameOffset) {
+ // System.out.println("abort 3b");
+ return false; // REVISIT
+ }
+ if (currentOffset < endOffset) {
+ ch = data.charAt(currentOffset);
+ }
+ else {
+ ch = -1;
+ }
+ nameHandle = symbolTable.addSymbol(data.substring(nameOffset, currentOffset));
+ if (ch != ':') {
+ prefixHandle = XMLSymbols.EMPTY_STRING;
+ } else {
+ prefixHandle = nameHandle;
+ if (++currentOffset == endOffset) {
+ // System.out.println("abort 4a");
+ return false; // REVISIT
+ }
+ nameOffset = currentOffset;
+ currentOffset = scanNCName(data, endOffset, currentOffset);
+ if (currentOffset == nameOffset) {
+ // System.out.println("abort 4b");
+ return false; // REVISIT
+ }
+ if (currentOffset < endOffset) {
+ ch = data.charAt(currentOffset);
+ }
+ else {
+ ch = -1;
+ }
+ nameHandle = symbolTable.addSymbol(data.substring(nameOffset, currentOffset));
+ }
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_VARIABLE_REFERENCE);
+ starIsMultiplyOperator = true;
+ tokens.addToken(prefixHandle);
+ tokens.addToken(nameHandle);
+ break;
+ //
+ // [37] NameTest ::= '*' | NCName ':' '*' | QName
+ // [34] MultiplyOperator ::= '*'
+ //
+ case CHARTYPE_STAR: // '*'
+ //
+ // 3.7 Lexical Structure
+ //
+ // If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
+ // an Operator, then a * must be recognized as a MultiplyOperator.
+ //
+ // Otherwise, the token must not be recognized as a MultiplyOperator.
+ //
+ if (starIsMultiplyOperator) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_MULT);
+ starIsMultiplyOperator = false;
+ } else {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_NAMETEST_ANY);
+ starIsMultiplyOperator = true;
+ }
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ //
+ // NCName, QName and non-terminals
+ //
+ case CHARTYPE_NONASCII: // possibly a valid non-ascii 'Letter' (BaseChar | Ideographic)
+ case CHARTYPE_LETTER:
+ case CHARTYPE_UNDERSCORE:
+ //
+ // 3.7 Lexical Structure
+ //
+ // If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
+ // an Operator, then an NCName must be recognized as an OperatorName.
+ //
+ // If the character following an NCName (possibly after intervening ExprWhitespace) is (,
+ // then the token must be recognized as a NodeType or a FunctionName.
+ //
+ // If the two characters following an NCName (possibly after intervening ExprWhitespace)
+ // are ::, then the token must be recognized as an AxisName.
+ //
+ // Otherwise, the token must not be recognized as an OperatorName, a NodeType, a
+ // FunctionName, or an AxisName.
+ //
+ // [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div'
+ // [38] NodeType ::= 'comment' | 'text' | 'processing-instruction' | 'node'
+ // [35] FunctionName ::= QName - NodeType
+ // [6] AxisName ::= (see above)
+ //
+ // [37] NameTest ::= '*' | NCName ':' '*' | QName
+ // [5] NCName ::= (Letter | '_') (NCNameChar)*
+ // [?] NCNameChar ::= Letter | Digit | '.' | '-' | '_' (ascii subset of 'NCNameChar')
+ // [?] QName ::= (NCName ':')? NCName
+ // [?] Letter ::= [A-Za-z] (ascii subset of 'Letter')
+ // [?] Digit ::= [0-9] (ascii subset of 'Digit')
+ //
+ nameOffset = currentOffset;
+ currentOffset = scanNCName(data, endOffset, currentOffset);
+ if (currentOffset == nameOffset) {
+ // System.out.println("abort 4c");
+ return false; // REVISIT
+ }
+ if (currentOffset < endOffset) {
+ ch = data.charAt(currentOffset);
+ }
+ else {
+ ch = -1;
+ }
+ nameHandle = symbolTable.addSymbol(data.substring(nameOffset, currentOffset));
+ boolean isNameTestNCName = false;
+ boolean isAxisName = false;
+ prefixHandle = XMLSymbols.EMPTY_STRING;
+ if (ch == ':') {
+ if (++currentOffset == endOffset) {
+ // System.out.println("abort 5");
+ return false; // REVISIT
+ }
+ ch = data.charAt(currentOffset);
+ if (ch == '*') {
+ if (++currentOffset < endOffset) {
+ ch = data.charAt(currentOffset);
+ }
+ isNameTestNCName = true;
+ } else if (ch == ':') {
+ if (++currentOffset < endOffset) {
+ ch = data.charAt(currentOffset);
+ }
+ isAxisName = true;
+ } else {
+ prefixHandle = nameHandle;
+ nameOffset = currentOffset;
+ currentOffset = scanNCName(data, endOffset, currentOffset);
+ if (currentOffset == nameOffset) {
+ // System.out.println("abort 5b");
+ return false; // REVISIT
+ }
+ if (currentOffset < endOffset) {
+ ch = data.charAt(currentOffset);
+ }
+ else {
+ ch = -1;
+ }
+ nameHandle = symbolTable.addSymbol(data.substring(nameOffset, currentOffset));
+ }
+ }
+ //
+ // [39] ExprWhitespace ::= S
+ //
+ while (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D) {
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ ch = data.charAt(currentOffset);
+ }
+ //
+ // If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
+ // an Operator, then an NCName must be recognized as an OperatorName.
+ //
+ if (starIsMultiplyOperator) {
+ if (nameHandle == fAndSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_AND);
+ starIsMultiplyOperator = false;
+ } else if (nameHandle == fOrSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_OR);
+ starIsMultiplyOperator = false;
+ } else if (nameHandle == fModSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_MOD);
+ starIsMultiplyOperator = false;
+ } else if (nameHandle == fDivSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPERATOR_DIV);
+ starIsMultiplyOperator = false;
+ } else {
+ // System.out.println("abort 6");
+ return false; // REVISIT
+ }
+ if (isNameTestNCName) {
+ // System.out.println("abort 7");
+ return false; // REVISIT - NCName:* where an OperatorName is required
+ } else if (isAxisName) {
+ // System.out.println("abort 8");
+ return false; // REVISIT - AxisName:: where an OperatorName is required
+ }
+ break;
+ }
+ //
+ // If the character following an NCName (possibly after intervening ExprWhitespace) is (,
+ // then the token must be recognized as a NodeType or a FunctionName.
+ //
+ if (ch == '(' && !isNameTestNCName && !isAxisName) {
+ if (nameHandle == fCommentSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_NODETYPE_COMMENT);
+ } else if (nameHandle == fTextSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_NODETYPE_TEXT);
+ } else if (nameHandle == fPISymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_NODETYPE_PI);
+ } else if (nameHandle == fNodeSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_NODETYPE_NODE);
+ } else {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_FUNCTION_NAME);
+ tokens.addToken(prefixHandle);
+ tokens.addToken(nameHandle);
+ }
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_OPEN_PAREN);
+ starIsMultiplyOperator = false;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ break;
+ }
+ //
+ // If the two characters following an NCName (possibly after intervening ExprWhitespace)
+ // are ::, then the token must be recognized as an AxisName.
+ //
+ if (isAxisName ||
+ (ch == ':' && currentOffset + 1 < endOffset &&
+ data.charAt(currentOffset + 1) == ':')) {
+ if (nameHandle == fAncestorSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_ANCESTOR);
+ } else if (nameHandle == fAncestorOrSelfSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF);
+ } else if (nameHandle == fAttributeSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE);
+ } else if (nameHandle == fChildSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD);
+ } else if (nameHandle == fDescendantSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_DESCENDANT);
+ } else if (nameHandle == fDescendantOrSelfSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF);
+ } else if (nameHandle == fFollowingSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_FOLLOWING);
+ } else if (nameHandle == fFollowingSiblingSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING);
+ } else if (nameHandle == fNamespaceSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_NAMESPACE);
+ } else if (nameHandle == fParentSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_PARENT);
+ } else if (nameHandle == fPrecedingSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_PRECEDING);
+ } else if (nameHandle == fPrecedingSiblingSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_PRECEDING_SIBLING);
+ } else if (nameHandle == fSelfSymbol) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_AXISNAME_SELF);
+ } else {
+ // System.out.println("abort 9");
+ return false; // REVISIT
+ }
+ if (isNameTestNCName) {
+ // System.out.println("abort 10");
+ return false; // REVISIT - "NCName:* ::" where "AxisName ::" is required
+ }
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_DOUBLE_COLON);
+ starIsMultiplyOperator = false;
+ if (!isAxisName) {
+ currentOffset++;
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ }
+ break;
+ }
+ //
+ // Otherwise, the token must not be recognized as an OperatorName, a NodeType, a
+ // FunctionName, or an AxisName.
+ //
+ if (isNameTestNCName) {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE);
+ starIsMultiplyOperator = true;
+ tokens.addToken(nameHandle);
+ } else {
+ addToken(tokens, XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME);
+ starIsMultiplyOperator = true;
+ tokens.addToken(prefixHandle);
+ tokens.addToken(nameHandle);
+ }
+ break;
+ default:
+ // CHARTYPE_INVALID or CHARTYPE_OTHER
+ // We're not expecting to find either of these in a valid expression.
+ return false;
+ }
+ }
+ if (XPath.Tokens.DUMP_TOKENS) {
+ tokens.dumpTokens();
+ }
+ return true;
+ }
+ //
+ // [5] NCName ::= (Letter | '_') (NCNameChar)*
+ // [6] NCNameChar ::= Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender
+ //
+ int scanNCName(String data, int endOffset, int currentOffset) {
+ int ch = data.charAt(currentOffset);
+ if (ch >= 0x80) {
+ if (!XMLChar.isNameStart(ch))
+ /*** // REVISIT: Make sure this is a negation. ***
+ if ((XMLCharacterProperties.fgCharFlags[ch] &
+ XMLCharacterProperties.E_InitialNameCharFlag) == 0)
+ /***/
+ {
+ return currentOffset;
+ }
+ }
+ else {
+ byte chartype = fASCIICharMap[ch];
+ if (chartype != CHARTYPE_LETTER && chartype != CHARTYPE_UNDERSCORE) {
+ return currentOffset;
+ }
+ }
+ while (++currentOffset < endOffset) {
+ ch = data.charAt(currentOffset);
+ if (ch >= 0x80) {
+ if (!XMLChar.isName(ch))
+ /*** // REVISIT: Make sure this is a negation. ***
+ if ((XMLCharacterProperties.fgCharFlags[ch] &
+ XMLCharacterProperties.E_NameCharFlag) == 0)
+ /***/
+ {
+ break;
+ }
+ }
+ else {
+ byte chartype = fASCIICharMap[ch];
+ if (chartype != CHARTYPE_LETTER && chartype != CHARTYPE_DIGIT &&
+ chartype != CHARTYPE_PERIOD && chartype != CHARTYPE_MINUS &&
+ chartype != CHARTYPE_UNDERSCORE)
+ {
+ break;
+ }
+ }
+ }
+ return currentOffset;
+ }
+ //
+ // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
+ // [31] Digits ::= [0-9]+
+ //
+ private int scanNumber(XPath.Tokens tokens, String/*byte[]*/ data, int endOffset, int currentOffset/*, EncodingSupport encoding*/) {
+ int ch = data.charAt(currentOffset);
+ int whole = 0;
+ int part = 0;
+ while (ch >= '0' && ch <= '9') {
+ whole = (whole * 10) + (ch - '0');
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ ch = data.charAt(currentOffset);
+ }
+ if (ch == '.') {
+ if (++currentOffset < endOffset) {
+ /** int start = currentOffset; **/
+ ch = data.charAt(currentOffset);
+ while (ch >= '0' && ch <= '9') {
+ part = (part * 10) + (ch - '0');
+ if (++currentOffset == endOffset) {
+ break;
+ }
+ ch = data.charAt(currentOffset);
+ }
+ if (part != 0) {
+ /***
+ part = tokens.addSymbol(data, start, currentOffset - start, encoding);
+ /***/
+ throw new RuntimeException("find a solution!");
+ //part = fStringPool.addSymbol(data.substring(start, currentOffset));
+ /***/
+ }
+ }
+ }
+ tokens.addToken(whole);
+ tokens.addToken(part);
+ return currentOffset;
+ }
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * This method adds the specified token to the token list. By
+ * default, this method allows all tokens. However, subclasses
+ * of the XPathExprScanner can override this method in order
+ * to disallow certain tokens from being used in the scanned
+ * XPath expression. This is a convenient way of allowing only
+ * a subset of XPath.
+ */
+ protected void addToken(XPath.Tokens tokens, int token)
+ throws XPathException {
+ tokens.addToken(token);
+ } // addToken(int)
+
+ } // class Scanner
+
+ //
+ // MAIN
+ //
+
+ /** Main program entry. */
+ public static void main(String[] argv) throws Exception {
+
+ for (int i = 0; i < argv.length; i++) {
+ final String expression = argv[i];
+ System.out.println("# XPath expression: \""+expression+'"');
+ try {
+ SymbolTable symbolTable = new SymbolTable();
+ XPath xpath = new XPath(expression, symbolTable, null);
+ System.out.println("expanded xpath: \""+xpath.toString()+'"');
+ }
+ catch (XPathException e) {
+ System.out.println("error: "+e.getMessage());
+ }
+ }
+
+ } // main(String[])
+
+} // class XPath
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xpath/XPathException.java b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/XPathException.java
new file mode 100644
index 0000000..e50c9b7
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/XPathException.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xpath;
+
+/**
+ * XPath exception.
+ *
+ * @xerces.internal
+ *
+ * @author Andy Clark, IBM
+ *
+ * @version $Id$
+ */
+public class XPathException
+ extends Exception {
+
+ /** Serialization version. */
+ static final long serialVersionUID = -948482312169512085L;
+
+ // Data
+
+ // hold the value of the key this Exception refers to.
+ private final String fKey;
+ //
+ // Constructors
+ //
+
+ /** Constructs an exception. */
+ public XPathException() {
+ super();
+ fKey = "c-general-xpath";
+ } // ()
+
+ /** Constructs an exception with the specified key. */
+ public XPathException(String key) {
+ super();
+ fKey = key;
+ } // (String)
+
+ public String getKey() {
+ return fKey;
+ } // getKey(): String
+
+} // class XPathException
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/BMPattern.java b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/BMPattern.java
new file mode 100644
index 0000000..d720af4
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/BMPattern.java
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xpath.regex;
+
+import java.text.CharacterIterator;
+
+/**
+ * Boyer-Moore searcher.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public class BMPattern {
+ final char[] pattern;
+ final int[] shiftTable;
+ final boolean ignoreCase;
+
+ public BMPattern(String pat, boolean ignoreCase) {
+ this(pat, 256, ignoreCase);
+ }
+
+ public BMPattern(String pat, int tableSize, boolean ignoreCase) {
+ this.pattern = pat.toCharArray();
+ this.shiftTable = new int[tableSize];
+ this.ignoreCase = ignoreCase;
+
+ int length = pattern.length;
+ for (int i = 0; i < this.shiftTable.length; i ++)
+ this.shiftTable[i] = length;
+
+ for (int i = 0; i < length; i ++) {
+ char ch = this.pattern[i];
+ int diff = length-i-1;
+ int index = ch % this.shiftTable.length;
+ if (diff < this.shiftTable[index])
+ this.shiftTable[index] = diff;
+ if (this.ignoreCase) {
+ ch = Character.toUpperCase(ch);
+ index = ch % this.shiftTable.length;
+ if (diff < this.shiftTable[index])
+ this.shiftTable[index] = diff;
+ ch = Character.toLowerCase(ch);
+ index = ch % this.shiftTable.length;
+ if (diff < this.shiftTable[index])
+ this.shiftTable[index] = diff;
+ }
+ }
+ }
+
+ /**
+ *
+ * @return -1 if iterator does not contain this pattern.
+ */
+ public int matches(CharacterIterator iterator, int start, int limit) {
+ if (this.ignoreCase) return this.matchesIgnoreCase(iterator, start, limit);
+ int plength = this.pattern.length;
+ if (plength == 0) return start;
+ int index = start+plength;
+ while (index <= limit) {
+ int pindex = plength;
+ int nindex = index+1;
+ char ch;
+ do {
+ if ((ch = iterator.setIndex(--index)) != this.pattern[--pindex])
+ break;
+ if (pindex == 0)
+ return index;
+ } while (pindex > 0);
+ index += this.shiftTable[ch % this.shiftTable.length]+1;
+ if (index < nindex) index = nindex;
+ }
+ return -1;
+ }
+
+ /**
+ *
+ * @return -1 if str does not contain this pattern.
+ */
+ public int matches(String str, int start, int limit) {
+ if (this.ignoreCase) return this.matchesIgnoreCase(str, start, limit);
+ int plength = this.pattern.length;
+ if (plength == 0) return start;
+ int index = start+plength;
+ while (index <= limit) {
+ //System.err.println("Starts at "+index);
+ int pindex = plength;
+ int nindex = index+1;
+ char ch;
+ do {
+ if ((ch = str.charAt(--index)) != this.pattern[--pindex])
+ break;
+ if (pindex == 0)
+ return index;
+ } while (pindex > 0);
+ index += this.shiftTable[ch % this.shiftTable.length]+1;
+ if (index < nindex) index = nindex;
+ }
+ return -1;
+ }
+ /**
+ *
+ * @return -1 if chars does not contain this pattern.
+ */
+ public int matches(char[] chars, int start, int limit) {
+ if (this.ignoreCase) return this.matchesIgnoreCase(chars, start, limit);
+ int plength = this.pattern.length;
+ if (plength == 0) return start;
+ int index = start+plength;
+ while (index <= limit) {
+ //System.err.println("Starts at "+index);
+ int pindex = plength;
+ int nindex = index+1;
+ char ch;
+ do {
+ if ((ch = chars[--index]) != this.pattern[--pindex])
+ break;
+ if (pindex == 0)
+ return index;
+ } while (pindex > 0);
+ index += this.shiftTable[ch % this.shiftTable.length]+1;
+ if (index < nindex) index = nindex;
+ }
+ return -1;
+ }
+
+ int matchesIgnoreCase(CharacterIterator iterator, int start, int limit) {
+ int plength = this.pattern.length;
+ if (plength == 0) return start;
+ int index = start+plength;
+ while (index <= limit) {
+ int pindex = plength;
+ int nindex = index+1;
+ char ch;
+ do {
+ char ch1 = ch = iterator.setIndex(--index);
+ char ch2 = this.pattern[--pindex];
+ if (ch1 != ch2) {
+ ch1 = Character.toUpperCase(ch1);
+ ch2 = Character.toUpperCase(ch2);
+ if (ch1 != ch2 && Character.toLowerCase(ch1) != Character.toLowerCase(ch2))
+ break;
+ }
+ if (pindex == 0)
+ return index;
+ } while (pindex > 0);
+ index += this.shiftTable[ch % this.shiftTable.length]+1;
+ if (index < nindex) index = nindex;
+ }
+ return -1;
+ }
+
+ int matchesIgnoreCase(String text, int start, int limit) {
+ int plength = this.pattern.length;
+ if (plength == 0) return start;
+ int index = start+plength;
+ while (index <= limit) {
+ int pindex = plength;
+ int nindex = index+1;
+ char ch;
+ do {
+ char ch1 = ch = text.charAt(--index);
+ char ch2 = this.pattern[--pindex];
+ if (ch1 != ch2) {
+ ch1 = Character.toUpperCase(ch1);
+ ch2 = Character.toUpperCase(ch2);
+ if (ch1 != ch2 && Character.toLowerCase(ch1) != Character.toLowerCase(ch2))
+ break;
+ }
+ if (pindex == 0)
+ return index;
+ } while (pindex > 0);
+ index += this.shiftTable[ch % this.shiftTable.length]+1;
+ if (index < nindex) index = nindex;
+ }
+ return -1;
+ }
+ int matchesIgnoreCase(char[] chars, int start, int limit) {
+ int plength = this.pattern.length;
+ if (plength == 0) return start;
+ int index = start+plength;
+ while (index <= limit) {
+ int pindex = plength;
+ int nindex = index+1;
+ char ch;
+ do {
+ char ch1 = ch = chars[--index];
+ char ch2 = this.pattern[--pindex];
+ if (ch1 != ch2) {
+ ch1 = Character.toUpperCase(ch1);
+ ch2 = Character.toUpperCase(ch2);
+ if (ch1 != ch2 && Character.toLowerCase(ch1) != Character.toLowerCase(ch2))
+ break;
+ }
+ if (pindex == 0)
+ return index;
+ } while (pindex > 0);
+ index += this.shiftTable[ch % this.shiftTable.length]+1;
+ if (index < nindex) index = nindex;
+ }
+ return -1;
+ }
+
+ /*
+ public static void main(String[] argv) {
+ try {
+ int[] shiftTable = new int[256];
+ initializeBoyerMoore(argv[0], shiftTable, true);
+ int o = -1;
+ CharacterIterator ite = new java.text.StringCharacterIterator(argv[1]);
+ long start = System.currentTimeMillis();
+ //for (int i = 0; i < 10000; i ++)
+ o = searchIgnoreCasesWithBoyerMoore(ite, 0, argv[0], shiftTable);
+ start = System.currentTimeMillis()-start;
+ System.out.println("Result: "+o+", Elapsed: "+start);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }*/
+}
+
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/CaseInsensitiveMap.java b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/CaseInsensitiveMap.java
new file mode 100644
index 0000000..010ead2
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/CaseInsensitiveMap.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xpath.regex;
+
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+final class CaseInsensitiveMap {
+
+ private static int CHUNK_SHIFT = 10; /* 2^10 = 1k */
+ private static int CHUNK_SIZE = (1<>> CHUNK_SHIFT;
+ int offset = codePoint & CHUNK_MASK;
+
+ return caseInsensitiveMap[chunk][offset];
+ }
+
+ private static void buildCaseInsensitiveMap() {
+ caseInsensitiveMap = new int[INITIAL_CHUNK_COUNT][CHUNK_SIZE][];
+ int lc, uc;
+ for (int i=0; i<0x10000; i++) {
+ lc = Character.toLowerCase((char) i);
+ uc = Character.toUpperCase((char) i);
+
+ // lower/upper case value is not the same as code point
+ if (lc != uc || lc != i) {
+ int[] map = new int[2];
+ int index = 0;
+
+ if (lc != i) {
+ map[index++] = lc;
+ map[index++] = LOWER_CASE_MATCH;
+ int[] lcMap = getMapping(lc);
+ if (lcMap != null) {
+ map = updateMap(i, map, lc, lcMap, LOWER_CASE_MATCH);
+ }
+ }
+
+ if (uc != i) {
+ if (index == map.length) {
+ map = expandMap(map, 2);
+ }
+ map[index++] = uc;
+ map[index++] = UPPER_CASE_MATCH;
+ int[] ucMap = getMapping(uc);
+ if (ucMap != null) {
+ map = updateMap(i, map, uc, ucMap, UPPER_CASE_MATCH);
+ }
+ }
+
+ set(i, map);
+ }
+ }
+ }
+
+ private static int[] expandMap(int[] srcMap, int expandBy) {
+ final int oldLen = srcMap.length;
+ int[] newMap = new int[oldLen + expandBy];
+
+ System.arraycopy(srcMap, 0, newMap, 0, oldLen);
+ return newMap;
+ }
+
+ private static void set(int codePoint, int[] map) {
+ int chunk = codePoint >>> CHUNK_SHIFT;
+ int offset = codePoint & CHUNK_MASK;
+
+ caseInsensitiveMap[chunk][offset] = map;
+ }
+
+ private static int[] updateMap(int codePoint, int[] codePointMap,
+ int ciCodePoint, int[] ciCodePointMap, int matchType) {
+ for (int i=0; i 0) {
+ ma.setNumberOfGroups(this.nofgroups);
+ if (this.ciSource != null) ma.setSource(this.ciSource);
+ if (this.strSource != null) ma.setSource(this.strSource);
+ for (int i = 0; i < this.nofgroups; i ++) {
+ ma.setBeginning(i, this.getBeginning(i));
+ ma.setEnd(i, this.getEnd(i));
+ }
+ }
+ return ma;
+ }
+
+ /**
+ *
+ */
+ protected void setNumberOfGroups(int n) {
+ int oldn = this.nofgroups;
+ this.nofgroups = n;
+ if (oldn <= 0
+ || oldn < n || n*2 < oldn) {
+ this.beginpos = new int[n];
+ this.endpos = new int[n];
+ }
+ for (int i = 0; i < n; i ++) {
+ this.beginpos[i] = -1;
+ this.endpos[i] = -1;
+ }
+ }
+
+ /**
+ *
+ */
+ protected void setSource(CharacterIterator ci) {
+ this.ciSource = ci;
+ this.strSource = null;
+ this.charSource = null;
+ }
+ /**
+ *
+ */
+ protected void setSource(String str) {
+ this.ciSource = null;
+ this.strSource = str;
+ this.charSource = null;
+ }
+ /**
+ *
+ */
+ protected void setSource(char[] chars) {
+ this.ciSource = null;
+ this.strSource = null;
+ this.charSource = chars;
+ }
+
+ /**
+ *
+ */
+ protected void setBeginning(int index, int v) {
+ this.beginpos[index] = v;
+ }
+
+ /**
+ *
+ */
+ protected void setEnd(int index, int v) {
+ this.endpos[index] = v;
+ }
+
+ /**
+ * Return the number of regular expression groups.
+ * This method returns 1 when the regular expression has no capturing-parenthesis.
+ */
+ public int getNumberOfGroups() {
+ if (this.nofgroups <= 0)
+ throw new IllegalStateException("A result is not set.");
+ return this.nofgroups;
+ }
+
+ /**
+ * Return a start position in the target text matched to specified regular expression group.
+ *
+ * @param index Less than getNumberOfGroups() .
+ */
+ public int getBeginning(int index) {
+ if (this.beginpos == null)
+ throw new IllegalStateException("A result is not set.");
+ if (index < 0 || this.nofgroups <= index)
+ throw new IllegalArgumentException("The parameter must be less than "
+ +this.nofgroups+": "+index);
+ return this.beginpos[index];
+ }
+
+ /**
+ * Return an end position in the target text matched to specified regular expression group.
+ *
+ * @param index Less than getNumberOfGroups() .
+ */
+ public int getEnd(int index) {
+ if (this.endpos == null)
+ throw new IllegalStateException("A result is not set.");
+ if (index < 0 || this.nofgroups <= index)
+ throw new IllegalArgumentException("The parameter must be less than "
+ +this.nofgroups+": "+index);
+ return this.endpos[index];
+ }
+
+ /**
+ * Return an substring of the target text matched to specified regular expression group.
+ *
+ * @param index Less than getNumberOfGroups() .
+ */
+ public String getCapturedText(int index) {
+ if (this.beginpos == null)
+ throw new IllegalStateException("match() has never been called.");
+ if (index < 0 || this.nofgroups <= index)
+ throw new IllegalArgumentException("The parameter must be less than "
+ +this.nofgroups+": "+index);
+ String ret;
+ int begin = this.beginpos[index], end = this.endpos[index];
+ if (begin < 0 || end < 0) return null;
+ if (this.ciSource != null) {
+ ret = REUtil.substring(this.ciSource, begin, end);
+ } else if (this.strSource != null) {
+ ret = this.strSource.substring(begin, end);
+ } else {
+ ret = new String(this.charSource, begin, end-begin);
+ }
+ return ret;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/Op.java b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/Op.java
new file mode 100644
index 0000000..c13b331
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/Op.java
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xpath.regex;
+
+import java.util.Vector;
+
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+class Op {
+ static final int DOT = 0;
+ static final int CHAR = 1; // Single character
+ static final int RANGE = 3; // [a-zA-Z]
+ static final int NRANGE = 4; // [^a-zA-Z]
+ static final int ANCHOR = 5; // ^ $ ...
+ static final int STRING = 6; // literal String
+ static final int CLOSURE = 7; // X*
+ static final int NONGREEDYCLOSURE = 8; // X*?
+ static final int QUESTION = 9; // X?
+ static final int NONGREEDYQUESTION = 10; // X??
+ static final int UNION = 11; // X|Y
+ static final int CAPTURE = 15; // ( and )
+ static final int BACKREFERENCE = 16; // \1 \2 ...
+ static final int LOOKAHEAD = 20; // (?=...)
+ static final int NEGATIVELOOKAHEAD = 21; // (?!...)
+ static final int LOOKBEHIND = 22; // (?<=...)
+ static final int NEGATIVELOOKBEHIND = 23; // (?...)
+ static final int MODIFIER = 25; // (?ims-ims:...)
+ static final int CONDITION = 26; // (?(..)yes|no)
+
+ static int nofinstances = 0;
+ static final boolean COUNT = false;
+
+ static Op createDot() {
+ if (Op.COUNT) Op.nofinstances ++;
+ return new Op(Op.DOT);
+ }
+ static CharOp createChar(int data) {
+ if (Op.COUNT) Op.nofinstances ++;
+ return new CharOp(Op.CHAR, data);
+ }
+ static CharOp createAnchor(int data) {
+ if (Op.COUNT) Op.nofinstances ++;
+ return new CharOp(Op.ANCHOR, data);
+ }
+ static CharOp createCapture(int number, Op next) {
+ if (Op.COUNT) Op.nofinstances ++;
+ CharOp op = new CharOp(Op.CAPTURE, number);
+ op.next = next;
+ return op;
+ }
+ static UnionOp createUnion(int size) {
+ if (Op.COUNT) Op.nofinstances ++;
+ //System.err.println("Creates UnionOp");
+ return new UnionOp(Op.UNION, size);
+ }
+ static ChildOp createClosure(int id) {
+ if (Op.COUNT) Op.nofinstances ++;
+ return new ModifierOp(Op.CLOSURE, id, -1);
+ }
+ static ChildOp createNonGreedyClosure() {
+ if (Op.COUNT) Op.nofinstances ++;
+ return new ChildOp(Op.NONGREEDYCLOSURE);
+ }
+ static ChildOp createQuestion(boolean nongreedy) {
+ if (Op.COUNT) Op.nofinstances ++;
+ return new ChildOp(nongreedy ? Op.NONGREEDYQUESTION : Op.QUESTION);
+ }
+ static RangeOp createRange(Token tok) {
+ if (Op.COUNT) Op.nofinstances ++;
+ return new RangeOp(Op.RANGE, tok);
+ }
+ static ChildOp createLook(int type, Op next, Op branch) {
+ if (Op.COUNT) Op.nofinstances ++;
+ ChildOp op = new ChildOp(type);
+ op.setChild(branch);
+ op.next = next;
+ return op;
+ }
+ static CharOp createBackReference(int refno) {
+ if (Op.COUNT) Op.nofinstances ++;
+ return new CharOp(Op.BACKREFERENCE, refno);
+ }
+ static StringOp createString(String literal) {
+ if (Op.COUNT) Op.nofinstances ++;
+ return new StringOp(Op.STRING, literal);
+ }
+ static ChildOp createIndependent(Op next, Op branch) {
+ if (Op.COUNT) Op.nofinstances ++;
+ ChildOp op = new ChildOp(Op.INDEPENDENT);
+ op.setChild(branch);
+ op.next = next;
+ return op;
+ }
+ static ModifierOp createModifier(Op next, Op branch, int add, int mask) {
+ if (Op.COUNT) Op.nofinstances ++;
+ ModifierOp op = new ModifierOp(Op.MODIFIER, add, mask);
+ op.setChild(branch);
+ op.next = next;
+ return op;
+ }
+ static ConditionOp createCondition(Op next, int ref, Op conditionflow, Op yesflow, Op noflow) {
+ if (Op.COUNT) Op.nofinstances ++;
+ ConditionOp op = new ConditionOp(Op.CONDITION, ref, conditionflow, yesflow, noflow);
+ op.next = next;
+ return op;
+ }
+
+ final int type;
+ Op next = null;
+
+ protected Op(int type) {
+ this.type = type;
+ }
+
+ int size() { // for UNION
+ return 0;
+ }
+ Op elementAt(int index) { // for UNIoN
+ throw new RuntimeException("Internal Error: type="+this.type);
+ }
+ Op getChild() { // for CLOSURE, QUESTION
+ throw new RuntimeException("Internal Error: type="+this.type);
+ }
+ // ModifierOp
+ int getData() { // CharOp for CHAR, BACKREFERENCE, CAPTURE, ANCHOR,
+ throw new RuntimeException("Internal Error: type="+this.type);
+ }
+ int getData2() { // ModifierOp
+ throw new RuntimeException("Internal Error: type="+this.type);
+ }
+ RangeToken getToken() { // RANGE, NRANGE
+ throw new RuntimeException("Internal Error: type="+this.type);
+ }
+ String getString() { // STRING
+ throw new RuntimeException("Internal Error: type="+this.type);
+ }
+
+ // ================================================================
+ static class CharOp extends Op {
+ final int charData;
+ CharOp(int type, int data) {
+ super(type);
+ this.charData = data;
+ }
+ int getData() {
+ return this.charData;
+ }
+ }
+
+ // ================================================================
+ static class UnionOp extends Op {
+ final Vector branches;
+ UnionOp(int type, int size) {
+ super(type);
+ this.branches = new Vector(size);
+ }
+ void addElement(Op op) {
+ this.branches.addElement(op);
+ }
+ int size() {
+ return this.branches.size();
+ }
+ Op elementAt(int index) {
+ return (Op)this.branches.elementAt(index);
+ }
+ }
+
+ // ================================================================
+ static class ChildOp extends Op {
+ Op child;
+ ChildOp(int type) {
+ super(type);
+ }
+ void setChild(Op child) {
+ this.child = child;
+ }
+ Op getChild() {
+ return this.child;
+ }
+ }
+ // ================================================================
+ static class ModifierOp extends ChildOp {
+ final int v1;
+ final int v2;
+ ModifierOp(int type, int v1, int v2) {
+ super(type);
+ this.v1 = v1;
+ this.v2 = v2;
+ }
+ int getData() {
+ return this.v1;
+ }
+ int getData2() {
+ return this.v2;
+ }
+ }
+ // ================================================================
+ static class RangeOp extends Op {
+ final Token tok;
+ RangeOp(int type, Token tok) {
+ super(type);
+ this.tok = tok;
+ }
+ RangeToken getToken() {
+ return (RangeToken)this.tok;
+ }
+ }
+ // ================================================================
+ static class StringOp extends Op {
+ final String string;
+ StringOp(int type, String literal) {
+ super(type);
+ this.string = literal;
+ }
+ String getString() {
+ return this.string;
+ }
+ }
+ // ================================================================
+ static class ConditionOp extends Op {
+ final int refNumber;
+ final Op condition;
+ final Op yes;
+ final Op no;
+ ConditionOp(int type, int refno, Op conditionflow, Op yesflow, Op noflow) {
+ super(type);
+ this.refNumber = refno;
+ this.condition = conditionflow;
+ this.yes = yesflow;
+ this.no = noflow;
+ }
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/ParseException.java b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/ParseException.java
new file mode 100644
index 0000000..134694b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/ParseException.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xpath.regex;
+
+/**
+ * @xerces.internal
+ *
+ * @author TAMURA Kent <kent@trl.ibm.co.jp>
+ * @version $Id$
+ */
+public class ParseException extends RuntimeException {
+
+ /** Serialization version. */
+ static final long serialVersionUID = -7012400318097691370L;
+
+ final int location;
+
+ /*
+ public ParseException(String mes) {
+ this(mes, -1);
+ }
+ */
+ /**
+ *
+ */
+ public ParseException(String mes, int location) {
+ super(mes);
+ this.location = location;
+ }
+
+ /**
+ *
+ * @return -1 if location information is not available.
+ */
+ public int getLocation() {
+ return this.location;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/ParserForXMLSchema.java b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/ParserForXMLSchema.java
new file mode 100644
index 0000000..fca38bb
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/ParserForXMLSchema.java
@@ -0,0 +1,514 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xpath.regex;
+
+import java.util.Hashtable;
+import java.util.Locale;
+
+/**
+ * A regular expression parser for the XML Schema.
+ *
+ * @xerces.internal
+ *
+ * @author TAMURA Kent <kent@trl.ibm.co.jp>
+ * @version $Id$
+ */
+class ParserForXMLSchema extends RegexParser {
+
+ public ParserForXMLSchema() {
+ //this.setLocale(Locale.getDefault());
+ }
+ public ParserForXMLSchema(Locale locale) {
+ super(locale);
+ }
+
+ Token processCaret() throws ParseException {
+ this.next();
+ return Token.createChar('^');
+ }
+ Token processDollar() throws ParseException {
+ this.next();
+ return Token.createChar('$');
+ }
+ Token processLookahead() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processNegativelookahead() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processLookbehind() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processNegativelookbehind() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processBacksolidus_A() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processBacksolidus_Z() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processBacksolidus_z() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processBacksolidus_b() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processBacksolidus_B() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processBacksolidus_lt() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processBacksolidus_gt() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processStar(Token tok) throws ParseException {
+ this.next();
+ return Token.createClosure(tok);
+ }
+ Token processPlus(Token tok) throws ParseException {
+ // X+ -> XX*
+ this.next();
+ return Token.createConcat(tok, Token.createClosure(tok));
+ }
+ Token processQuestion(Token tok) throws ParseException {
+ // X? -> X|
+ this.next();
+ Token par = Token.createUnion();
+ par.addChild(tok);
+ par.addChild(Token.createEmpty());
+ return par;
+ }
+ boolean checkQuestion(int off) {
+ return false;
+ }
+ Token processParen() throws ParseException {
+ this.next();
+ Token tok = Token.createParen(this.parseRegex(), 0);
+ if (this.read() != T_RPAREN) throw ex("parser.factor.1", this.offset-1);
+ this.next(); // Skips ')'
+ return tok;
+ }
+ Token processParen2() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processCondition() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processModifiers() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processIndependent() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processBacksolidus_c() throws ParseException {
+ this.next();
+ return this.getTokenForShorthand('c');
+ }
+ Token processBacksolidus_C() throws ParseException {
+ this.next();
+ return this.getTokenForShorthand('C');
+ }
+ Token processBacksolidus_i() throws ParseException {
+ this.next();
+ return this.getTokenForShorthand('i');
+ }
+ Token processBacksolidus_I() throws ParseException {
+ this.next();
+ return this.getTokenForShorthand('I');
+ }
+ Token processBacksolidus_g() throws ParseException {
+ throw this.ex("parser.process.1", this.offset-2);
+ }
+ Token processBacksolidus_X() throws ParseException {
+ throw ex("parser.process.1", this.offset-2);
+ }
+ Token processBackreference() throws ParseException {
+ throw ex("parser.process.1", this.offset-4);
+ }
+
+ int processCIinCharacterClass(RangeToken tok, int c) {
+ tok.mergeRanges(this.getTokenForShorthand(c));
+ return -1;
+ }
+
+
+ /**
+ * Parses a character-class-expression, not a character-class-escape.
+ *
+ * c-c-expression ::= '[' c-group ']'
+ * c-group ::= positive-c-group | negative-c-group | c-c-subtraction
+ * positive-c-group ::= (c-range | c-c-escape)+
+ * negative-c-group ::= '^' positive-c-group
+ * c-c-subtraction ::= (positive-c-group | negative-c-group) subtraction
+ * subtraction ::= '-' c-c-expression
+ * c-range ::= single-range | from-to-range
+ * single-range ::= multi-c-escape | category-c-escape | block-c-escape | <any XML char>
+ * cc-normal-c ::= <any character except [, ], \>
+ * from-to-range ::= cc-normal-c '-' cc-normal-c
+ *
+ * @param useNrage Ignored.
+ * @return This returns no NrageToken.
+ */
+ protected RangeToken parseCharacterClass(boolean useNrange) throws ParseException {
+ this.setContext(S_INBRACKETS);
+ this.next(); // '['
+ boolean nrange = false;
+ boolean wasDecoded = false; // used to detect if the last - was escaped.
+ RangeToken base = null;
+ RangeToken tok;
+ if (this.read() == T_CHAR && this.chardata == '^') {
+ nrange = true;
+ this.next(); // '^'
+ base = Token.createRange();
+ base.addRange(0, Token.UTF16_MAX);
+ tok = Token.createRange();
+ } else {
+ tok = Token.createRange();
+ }
+ int type;
+ boolean firstloop = true;
+ while ((type = this.read()) != T_EOF) { // Don't use 'cotinue' for this loop.
+
+ wasDecoded = false;
+ // single-range | from-to-range | subtraction
+ if (type == T_CHAR && this.chardata == ']' && !firstloop) {
+ if (nrange) {
+ base.subtractRanges(tok);
+ tok = base;
+ }
+ break;
+ }
+ int c = this.chardata;
+ boolean end = false;
+ if (type == T_BACKSOLIDUS) {
+ switch (c) {
+ case 'd': case 'D':
+ case 'w': case 'W':
+ case 's': case 'S':
+ tok.mergeRanges(this.getTokenForShorthand(c));
+ end = true;
+ break;
+
+ case 'i': case 'I':
+ case 'c': case 'C':
+ c = this.processCIinCharacterClass(tok, c);
+ if (c < 0) end = true;
+ break;
+
+ case 'p':
+ case 'P':
+ int pstart = this.offset;
+ RangeToken tok2 = this.processBacksolidus_pP(c);
+ if (tok2 == null) throw this.ex("parser.atom.5", pstart);
+ tok.mergeRanges(tok2);
+ end = true;
+ break;
+
+ case '-':
+ c = this.decodeEscaped();
+ wasDecoded = true;
+ break;
+
+ default:
+ c = this.decodeEscaped();
+ } // \ + c
+ } // backsolidus
+ else if (type == T_XMLSCHEMA_CC_SUBTRACTION && !firstloop) {
+ // Subraction
+ if (nrange) {
+ base.subtractRanges(tok);
+ tok = base;
+ }
+ RangeToken range2 = this.parseCharacterClass(false);
+ tok.subtractRanges(range2);
+ if (this.read() != T_CHAR || this.chardata != ']')
+ throw this.ex("parser.cc.5", this.offset);
+ break; // Exit this loop
+ }
+ this.next();
+ if (!end) { // if not shorthands...
+ if (type == T_CHAR) {
+ if (c == '[') throw this.ex("parser.cc.6", this.offset-2);
+ if (c == ']') throw this.ex("parser.cc.7", this.offset-2);
+ if (c == '-' && this.chardata != ']' && !firstloop) throw this.ex("parser.cc.8", this.offset-2); // if regex = '[-]' then invalid
+ }
+ if (this.read() != T_CHAR || this.chardata != '-' || c == '-' && !wasDecoded && firstloop) { // Here is no '-'.
+ if (!this.isSet(RegularExpression.IGNORE_CASE) || c > 0xffff) {
+ tok.addRange(c, c);
+ }
+ else {
+ addCaseInsensitiveChar(tok, c);
+ }
+ } else { // Found '-'
+ // Is this '-' is a from-to token??
+ this.next(); // Skips '-'
+ if ((type = this.read()) == T_EOF) throw this.ex("parser.cc.2", this.offset);
+ // c '-' ']' -> '-' is a single-range.
+ if(type == T_CHAR && this.chardata == ']') { // if - is at the last position of the group
+ if (!this.isSet(RegularExpression.IGNORE_CASE) || c > 0xffff) {
+ tok.addRange(c, c);
+ }
+ else {
+ addCaseInsensitiveChar(tok, c);
+ }
+ tok.addRange('-', '-');
+ }
+ else if (type == T_XMLSCHEMA_CC_SUBTRACTION) {
+ throw this.ex("parser.cc.8", this.offset-1);
+ } else {
+
+ int rangeend = this.chardata;
+ if (type == T_CHAR) {
+ if (rangeend == '[') throw this.ex("parser.cc.6", this.offset-1);
+ if (rangeend == ']') throw this.ex("parser.cc.7", this.offset-1);
+ if (rangeend == '-') throw this.ex("parser.cc.8", this.offset-2);
+ }
+ else if (type == T_BACKSOLIDUS)
+ rangeend = this.decodeEscaped();
+ this.next();
+
+ if (c > rangeend) throw this.ex("parser.ope.3", this.offset-1);
+ if (!this.isSet(RegularExpression.IGNORE_CASE) ||
+ (c > 0xffff && rangeend > 0xffff)) {
+ tok.addRange(c, rangeend);
+ }
+ else {
+ addCaseInsensitiveCharRange(tok, c, rangeend);
+ }
+ }
+ }
+ }
+ firstloop = false;
+ }
+ if (this.read() == T_EOF)
+ throw this.ex("parser.cc.2", this.offset);
+ tok.sortRanges();
+ tok.compactRanges();
+ //tok.dumpRanges();
+ this.setContext(S_NORMAL);
+ this.next(); // Skips ']'
+
+ return tok;
+ }
+
+ protected RangeToken parseSetOperations() throws ParseException {
+ throw this.ex("parser.process.1", this.offset);
+ }
+
+ Token getTokenForShorthand(int ch) {
+ switch (ch) {
+ case 'd':
+ return ParserForXMLSchema.getRange("xml:isDigit", true);
+ case 'D':
+ return ParserForXMLSchema.getRange("xml:isDigit", false);
+ case 'w':
+ return ParserForXMLSchema.getRange("xml:isWord", true);
+ case 'W':
+ return ParserForXMLSchema.getRange("xml:isWord", false);
+ case 's':
+ return ParserForXMLSchema.getRange("xml:isSpace", true);
+ case 'S':
+ return ParserForXMLSchema.getRange("xml:isSpace", false);
+ case 'c':
+ return ParserForXMLSchema.getRange("xml:isNameChar", true);
+ case 'C':
+ return ParserForXMLSchema.getRange("xml:isNameChar", false);
+ case 'i':
+ return ParserForXMLSchema.getRange("xml:isInitialNameChar", true);
+ case 'I':
+ return ParserForXMLSchema.getRange("xml:isInitialNameChar", false);
+ default:
+ throw new RuntimeException("Internal Error: shorthands: \\u"+Integer.toString(ch, 16));
+ }
+ }
+ int decodeEscaped() throws ParseException {
+ if (this.read() != T_BACKSOLIDUS) throw ex("parser.next.1", this.offset-1);
+ int c = this.chardata;
+ switch (c) {
+ case 'n': c = '\n'; break; // LINE FEED U+000A
+ case 'r': c = '\r'; break; // CRRIAGE RETURN U+000D
+ case 't': c = '\t'; break; // HORIZONTAL TABULATION U+0009
+ case '\\':
+ case '|':
+ case '.':
+ case '^':
+ case '-':
+ case '?':
+ case '*':
+ case '+':
+ case '{':
+ case '}':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ break; // return actucal char
+ default:
+ throw ex("parser.process.1", this.offset-2);
+ }
+ return c;
+ }
+
+ static private Hashtable ranges = null;
+ static private Hashtable ranges2 = null;
+ static synchronized protected RangeToken getRange(String name, boolean positive) {
+ if (ranges == null) {
+ ranges = new Hashtable();
+ ranges2 = new Hashtable();
+
+ Token tok = Token.createRange();
+ setupRange(tok, SPACES);
+ ranges.put("xml:isSpace", tok);
+ ranges2.put("xml:isSpace", Token.complementRanges(tok));
+
+ tok = Token.createRange();
+// setupRange(tok, DIGITS);
+ setupRange(tok, DIGITS_INTS);
+ ranges.put("xml:isDigit", tok);
+ ranges2.put("xml:isDigit", Token.complementRanges(tok));
+
+ /*
+ * \w is defined by the XML Schema specification to be:
+ * [#x0000-#x10FFFF]-[\p{P}\p{Z}\p{C}] (all characters except the set of "punctuation", "separator" and "other" characters)
+ */
+ tok = Token.createRange();
+ tok.mergeRanges(Token.getRange("P", true));
+ tok.mergeRanges(Token.getRange("Z", true));
+ tok.mergeRanges(Token.getRange("C", true));
+ ranges2.put("xml:isWord", tok);
+ ranges.put("xml:isWord", Token.complementRanges(tok));
+
+ tok = Token.createRange();
+ setupRange(tok, NAMECHARS);
+ ranges.put("xml:isNameChar", tok);
+ ranges2.put("xml:isNameChar", Token.complementRanges(tok));
+
+ tok = Token.createRange();
+ setupRange(tok, LETTERS);
+ tok.addRange('_', '_');
+ tok.addRange(':', ':');
+ ranges.put("xml:isInitialNameChar", tok);
+ ranges2.put("xml:isInitialNameChar", Token.complementRanges(tok));
+ }
+ RangeToken tok = positive ? (RangeToken)ranges.get(name)
+ : (RangeToken)ranges2.get(name);
+ return tok;
+ }
+
+ static void setupRange(Token range, String src) {
+ int len = src.length();
+ for (int i = 0; i < len; i += 2)
+ range.addRange(src.charAt(i), src.charAt(i+1));
+ }
+
+ static void setupRange(Token range, int[] src) {
+ int len = src.length;
+ for (int i = 0; i < len; i += 2)
+ range.addRange(src[i], src[i+1]);
+ }
+
+ private static final String SPACES = "\t\n\r\r ";
+ private static final String NAMECHARS =
+ "\u002d\u002e\u0030\u003a\u0041\u005a\u005f\u005f\u0061\u007a\u00b7\u00b7\u00c0\u00d6"
+ +"\u00d8\u00f6\u00f8\u0131\u0134\u013e\u0141\u0148\u014a\u017e\u0180\u01c3\u01cd\u01f0"
+ +"\u01f4\u01f5\u01fa\u0217\u0250\u02a8\u02bb\u02c1\u02d0\u02d1\u0300\u0345\u0360\u0361"
+ +"\u0386\u038a\u038c\u038c\u038e\u03a1\u03a3\u03ce\u03d0\u03d6\u03da\u03da\u03dc\u03dc"
+ +"\u03de\u03de\u03e0\u03e0\u03e2\u03f3\u0401\u040c\u040e\u044f\u0451\u045c\u045e\u0481"
+ +"\u0483\u0486\u0490\u04c4\u04c7\u04c8\u04cb\u04cc\u04d0\u04eb\u04ee\u04f5\u04f8\u04f9"
+ +"\u0531\u0556\u0559\u0559\u0561\u0586\u0591\u05a1\u05a3\u05b9\u05bb\u05bd\u05bf\u05bf"
+ +"\u05c1\u05c2\u05c4\u05c4\u05d0\u05ea\u05f0\u05f2\u0621\u063a\u0640\u0652\u0660\u0669"
+ +"\u0670\u06b7\u06ba\u06be\u06c0\u06ce\u06d0\u06d3\u06d5\u06e8\u06ea\u06ed\u06f0\u06f9"
+ +"\u0901\u0903\u0905\u0939\u093c\u094d\u0951\u0954\u0958\u0963\u0966\u096f\u0981\u0983"
+ +"\u0985\u098c\u098f\u0990\u0993\u09a8\u09aa\u09b0\u09b2\u09b2\u09b6\u09b9\u09bc\u09bc"
+ +"\u09be\u09c4\u09c7\u09c8\u09cb\u09cd\u09d7\u09d7\u09dc\u09dd\u09df\u09e3\u09e6\u09f1"
+ +"\u0a02\u0a02\u0a05\u0a0a\u0a0f\u0a10\u0a13\u0a28\u0a2a\u0a30\u0a32\u0a33\u0a35\u0a36"
+ +"\u0a38\u0a39\u0a3c\u0a3c\u0a3e\u0a42\u0a47\u0a48\u0a4b\u0a4d\u0a59\u0a5c\u0a5e\u0a5e"
+ +"\u0a66\u0a74\u0a81\u0a83\u0a85\u0a8b\u0a8d\u0a8d\u0a8f\u0a91\u0a93\u0aa8\u0aaa\u0ab0"
+ +"\u0ab2\u0ab3\u0ab5\u0ab9\u0abc\u0ac5\u0ac7\u0ac9\u0acb\u0acd\u0ae0\u0ae0\u0ae6\u0aef"
+ +"\u0b01\u0b03\u0b05\u0b0c\u0b0f\u0b10\u0b13\u0b28\u0b2a\u0b30\u0b32\u0b33\u0b36\u0b39"
+ +"\u0b3c\u0b43\u0b47\u0b48\u0b4b\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f\u0b61\u0b66\u0b6f"
+ +"\u0b82\u0b83\u0b85\u0b8a\u0b8e\u0b90\u0b92\u0b95\u0b99\u0b9a\u0b9c\u0b9c\u0b9e\u0b9f"
+ +"\u0ba3\u0ba4\u0ba8\u0baa\u0bae\u0bb5\u0bb7\u0bb9\u0bbe\u0bc2\u0bc6\u0bc8\u0bca\u0bcd"
+ +"\u0bd7\u0bd7\u0be7\u0bef\u0c01\u0c03\u0c05\u0c0c\u0c0e\u0c10\u0c12\u0c28\u0c2a\u0c33"
+ +"\u0c35\u0c39\u0c3e\u0c44\u0c46\u0c48\u0c4a\u0c4d\u0c55\u0c56\u0c60\u0c61\u0c66\u0c6f"
+ +"\u0c82\u0c83\u0c85\u0c8c\u0c8e\u0c90\u0c92\u0ca8\u0caa\u0cb3\u0cb5\u0cb9\u0cbe\u0cc4"
+ +"\u0cc6\u0cc8\u0cca\u0ccd\u0cd5\u0cd6\u0cde\u0cde\u0ce0\u0ce1\u0ce6\u0cef\u0d02\u0d03"
+ +"\u0d05\u0d0c\u0d0e\u0d10\u0d12\u0d28\u0d2a\u0d39\u0d3e\u0d43\u0d46\u0d48\u0d4a\u0d4d"
+ +"\u0d57\u0d57\u0d60\u0d61\u0d66\u0d6f\u0e01\u0e2e\u0e30\u0e3a\u0e40\u0e4e\u0e50\u0e59"
+ +"\u0e81\u0e82\u0e84\u0e84\u0e87\u0e88\u0e8a\u0e8a\u0e8d\u0e8d\u0e94\u0e97\u0e99\u0e9f"
+ +"\u0ea1\u0ea3\u0ea5\u0ea5\u0ea7\u0ea7\u0eaa\u0eab\u0ead\u0eae\u0eb0\u0eb9\u0ebb\u0ebd"
+ +"\u0ec0\u0ec4\u0ec6\u0ec6\u0ec8\u0ecd\u0ed0\u0ed9\u0f18\u0f19\u0f20\u0f29\u0f35\u0f35"
+ +"\u0f37\u0f37\u0f39\u0f39\u0f3e\u0f47\u0f49\u0f69\u0f71\u0f84\u0f86\u0f8b\u0f90\u0f95"
+ +"\u0f97\u0f97\u0f99\u0fad\u0fb1\u0fb7\u0fb9\u0fb9\u10a0\u10c5\u10d0\u10f6\u1100\u1100"
+ +"\u1102\u1103\u1105\u1107\u1109\u1109\u110b\u110c\u110e\u1112\u113c\u113c\u113e\u113e"
+ +"\u1140\u1140\u114c\u114c\u114e\u114e\u1150\u1150\u1154\u1155\u1159\u1159\u115f\u1161"
+ +"\u1163\u1163\u1165\u1165\u1167\u1167\u1169\u1169\u116d\u116e\u1172\u1173\u1175\u1175"
+ +"\u119e\u119e\u11a8\u11a8\u11ab\u11ab\u11ae\u11af\u11b7\u11b8\u11ba\u11ba\u11bc\u11c2"
+ +"\u11eb\u11eb\u11f0\u11f0\u11f9\u11f9\u1e00\u1e9b\u1ea0\u1ef9\u1f00\u1f15\u1f18\u1f1d"
+ +"\u1f20\u1f45\u1f48\u1f4d\u1f50\u1f57\u1f59\u1f59\u1f5b\u1f5b\u1f5d\u1f5d\u1f5f\u1f7d"
+ +"\u1f80\u1fb4\u1fb6\u1fbc\u1fbe\u1fbe\u1fc2\u1fc4\u1fc6\u1fcc\u1fd0\u1fd3\u1fd6\u1fdb"
+ +"\u1fe0\u1fec\u1ff2\u1ff4\u1ff6\u1ffc\u20d0\u20dc\u20e1\u20e1\u2126\u2126\u212a\u212b"
+ +"\u212e\u212e\u2180\u2182\u3005\u3005\u3007\u3007\u3021\u302f\u3031\u3035\u3041\u3094"
+ +"\u3099\u309a\u309d\u309e\u30a1\u30fa\u30fc\u30fe\u3105\u312c\u4e00\u9fa5\uac00\ud7a3"
+ +"";
+ private static final String LETTERS =
+ "\u0041\u005a\u0061\u007a\u00c0\u00d6\u00d8\u00f6\u00f8\u0131\u0134\u013e\u0141\u0148"
+ +"\u014a\u017e\u0180\u01c3\u01cd\u01f0\u01f4\u01f5\u01fa\u0217\u0250\u02a8\u02bb\u02c1"
+ +"\u0386\u0386\u0388\u038a\u038c\u038c\u038e\u03a1\u03a3\u03ce\u03d0\u03d6\u03da\u03da"
+ +"\u03dc\u03dc\u03de\u03de\u03e0\u03e0\u03e2\u03f3\u0401\u040c\u040e\u044f\u0451\u045c"
+ +"\u045e\u0481\u0490\u04c4\u04c7\u04c8\u04cb\u04cc\u04d0\u04eb\u04ee\u04f5\u04f8\u04f9"
+ +"\u0531\u0556\u0559\u0559\u0561\u0586\u05d0\u05ea\u05f0\u05f2\u0621\u063a\u0641\u064a"
+ +"\u0671\u06b7\u06ba\u06be\u06c0\u06ce\u06d0\u06d3\u06d5\u06d5\u06e5\u06e6\u0905\u0939"
+ +"\u093d\u093d\u0958\u0961\u0985\u098c\u098f\u0990\u0993\u09a8\u09aa\u09b0\u09b2\u09b2"
+ +"\u09b6\u09b9\u09dc\u09dd\u09df\u09e1\u09f0\u09f1\u0a05\u0a0a\u0a0f\u0a10\u0a13\u0a28"
+ +"\u0a2a\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59\u0a5c\u0a5e\u0a5e\u0a72\u0a74"
+ +"\u0a85\u0a8b\u0a8d\u0a8d\u0a8f\u0a91\u0a93\u0aa8\u0aaa\u0ab0\u0ab2\u0ab3\u0ab5\u0ab9"
+ +"\u0abd\u0abd\u0ae0\u0ae0\u0b05\u0b0c\u0b0f\u0b10\u0b13\u0b28\u0b2a\u0b30\u0b32\u0b33"
+ +"\u0b36\u0b39\u0b3d\u0b3d\u0b5c\u0b5d\u0b5f\u0b61\u0b85\u0b8a\u0b8e\u0b90\u0b92\u0b95"
+ +"\u0b99\u0b9a\u0b9c\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8\u0baa\u0bae\u0bb5\u0bb7\u0bb9"
+ +"\u0c05\u0c0c\u0c0e\u0c10\u0c12\u0c28\u0c2a\u0c33\u0c35\u0c39\u0c60\u0c61\u0c85\u0c8c"
+ +"\u0c8e\u0c90\u0c92\u0ca8\u0caa\u0cb3\u0cb5\u0cb9\u0cde\u0cde\u0ce0\u0ce1\u0d05\u0d0c"
+ +"\u0d0e\u0d10\u0d12\u0d28\u0d2a\u0d39\u0d60\u0d61\u0e01\u0e2e\u0e30\u0e30\u0e32\u0e33"
+ +"\u0e40\u0e45\u0e81\u0e82\u0e84\u0e84\u0e87\u0e88\u0e8a\u0e8a\u0e8d\u0e8d\u0e94\u0e97"
+ +"\u0e99\u0e9f\u0ea1\u0ea3\u0ea5\u0ea5\u0ea7\u0ea7\u0eaa\u0eab\u0ead\u0eae\u0eb0\u0eb0"
+ +"\u0eb2\u0eb3\u0ebd\u0ebd\u0ec0\u0ec4\u0f40\u0f47\u0f49\u0f69\u10a0\u10c5\u10d0\u10f6"
+ +"\u1100\u1100\u1102\u1103\u1105\u1107\u1109\u1109\u110b\u110c\u110e\u1112\u113c\u113c"
+ +"\u113e\u113e\u1140\u1140\u114c\u114c\u114e\u114e\u1150\u1150\u1154\u1155\u1159\u1159"
+ +"\u115f\u1161\u1163\u1163\u1165\u1165\u1167\u1167\u1169\u1169\u116d\u116e\u1172\u1173"
+ +"\u1175\u1175\u119e\u119e\u11a8\u11a8\u11ab\u11ab\u11ae\u11af\u11b7\u11b8\u11ba\u11ba"
+ +"\u11bc\u11c2\u11eb\u11eb\u11f0\u11f0\u11f9\u11f9\u1e00\u1e9b\u1ea0\u1ef9\u1f00\u1f15"
+ +"\u1f18\u1f1d\u1f20\u1f45\u1f48\u1f4d\u1f50\u1f57\u1f59\u1f59\u1f5b\u1f5b\u1f5d\u1f5d"
+ +"\u1f5f\u1f7d\u1f80\u1fb4\u1fb6\u1fbc\u1fbe\u1fbe\u1fc2\u1fc4\u1fc6\u1fcc\u1fd0\u1fd3"
+ +"\u1fd6\u1fdb\u1fe0\u1fec\u1ff2\u1ff4\u1ff6\u1ffc\u2126\u2126\u212a\u212b\u212e\u212e"
+ +"\u2180\u2182\u3007\u3007\u3021\u3029\u3041\u3094\u30a1\u30fa\u3105\u312c\u4e00\u9fa5"
+ +"\uac00\ud7a3";
+ private static final String DIGITS =
+ "\u0030\u0039\u0660\u0669\u06F0\u06F9\u0966\u096F\u09E6\u09EF\u0A66\u0A6F\u0AE6\u0AEF"
+ +"\u0B66\u0B6F\u0BE7\u0BEF\u0C66\u0C6F\u0CE6\u0CEF\u0D66\u0D6F\u0E50\u0E59\u0ED0\u0ED9"
+ +"\u0F20\u0F29";
+ private static final int[] DIGITS_INTS = {
+ 0x0030, 0x0039, 0x0660, 0x0669, 0x06F0, 0x06F9, 0x0966, 0x096F,
+ 0x09E6, 0x09EF, 0x0A66, 0x0A6F, 0x0AE6, 0x0AEF, 0x0B66, 0x0B6F,
+ 0x0BE7, 0x0BEF, 0x0C66, 0x0C6F, 0x0CE6, 0x0CEF, 0x0D66, 0x0D6F,
+ 0x0E50, 0x0E59, 0x0ED0, 0x0ED9, 0x0F20, 0x0F29, 0x1040, 0x1049,
+ 0x1369, 0x1371, 0x17E0, 0x17E9, 0x1810, 0x1819, 0xFF10, 0xFF19,
+ 0x1D7CE, 0x1D7FF
+ };
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/REUtil.java b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/REUtil.java
new file mode 100644
index 0000000..2c54732
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/REUtil.java
@@ -0,0 +1,363 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xpath.regex;
+
+import java.text.CharacterIterator;
+
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+public final class REUtil {
+ private REUtil() {
+ }
+
+ static final int composeFromSurrogates(int high, int low) {
+ return 0x10000 + ((high-0xd800)<<10) + low-0xdc00;
+ }
+
+ static final boolean isLowSurrogate(int ch) {
+ return (ch & 0xfc00) == 0xdc00;
+ }
+
+ static final boolean isHighSurrogate(int ch) {
+ return (ch & 0xfc00) == 0xd800;
+ }
+
+ static final String decomposeToSurrogates(int ch) {
+ char[] chs = new char[2];
+ ch -= 0x10000;
+ chs[0] = (char)((ch>>10)+0xd800);
+ chs[1] = (char)((ch&0x3ff)+0xdc00);
+ return new String(chs);
+ }
+
+ static final String substring(CharacterIterator iterator, int begin, int end) {
+ char[] src = new char[end-begin];
+ for (int i = 0; i < src.length; i ++)
+ src[i] = iterator.setIndex(i+begin);
+ return new String(src);
+ }
+
+ // ================================================================
+
+ static final int getOptionValue(int ch) {
+ int ret = 0;
+ switch (ch) {
+ case 'i':
+ ret = RegularExpression.IGNORE_CASE;
+ break;
+ case 'm':
+ ret = RegularExpression.MULTIPLE_LINES;
+ break;
+ case 's':
+ ret = RegularExpression.SINGLE_LINE;
+ break;
+ case 'x':
+ ret = RegularExpression.EXTENDED_COMMENT;
+ break;
+ case 'u':
+ ret = RegularExpression.USE_UNICODE_CATEGORY;
+ break;
+ case 'w':
+ ret = RegularExpression.UNICODE_WORD_BOUNDARY;
+ break;
+ case 'F':
+ ret = RegularExpression.PROHIBIT_FIXED_STRING_OPTIMIZATION;
+ break;
+ case 'H':
+ ret = RegularExpression.PROHIBIT_HEAD_CHARACTER_OPTIMIZATION;
+ break;
+ case 'X':
+ ret = RegularExpression.XMLSCHEMA_MODE;
+ break;
+ case ',':
+ ret = RegularExpression.SPECIAL_COMMA;
+ break;
+ default:
+ }
+ return ret;
+ }
+
+ static final int parseOptions(String opts) throws ParseException {
+ if (opts == null) return 0;
+ int options = 0;
+ for (int i = 0; i < opts.length(); i ++) {
+ int v = getOptionValue(opts.charAt(i));
+ if (v == 0)
+ throw new ParseException("Unknown Option: "+opts.substring(i), -1);
+ options |= v;
+ }
+ return options;
+ }
+
+ static final String createOptionString(int options) {
+ StringBuffer sb = new StringBuffer(9);
+ if ((options & RegularExpression.PROHIBIT_FIXED_STRING_OPTIMIZATION) != 0)
+ sb.append((char)'F');
+ if ((options & RegularExpression.PROHIBIT_HEAD_CHARACTER_OPTIMIZATION) != 0)
+ sb.append((char)'H');
+ if ((options & RegularExpression.XMLSCHEMA_MODE) != 0)
+ sb.append((char)'X');
+ if ((options & RegularExpression.IGNORE_CASE) != 0)
+ sb.append((char)'i');
+ if ((options & RegularExpression.MULTIPLE_LINES) != 0)
+ sb.append((char)'m');
+ if ((options & RegularExpression.SINGLE_LINE) != 0)
+ sb.append((char)'s');
+ if ((options & RegularExpression.USE_UNICODE_CATEGORY) != 0)
+ sb.append((char)'u');
+ if ((options & RegularExpression.UNICODE_WORD_BOUNDARY) != 0)
+ sb.append((char)'w');
+ if ((options & RegularExpression.EXTENDED_COMMENT) != 0)
+ sb.append((char)'x');
+ if ((options & RegularExpression.SPECIAL_COMMA) != 0)
+ sb.append((char)',');
+ return sb.toString().intern();
+ }
+
+ // ================================================================
+
+ static String stripExtendedComment(String regex) {
+ int len = regex.length();
+ StringBuffer buffer = new StringBuffer(len);
+ int offset = 0;
+ int charClass = 0;
+ while (offset < len) {
+ int ch = regex.charAt(offset++);
+ // Skips a white space.
+ if (ch == '\t' || ch == '\n' || ch == '\f' || ch == '\r' || ch == ' ') {
+ // if we are inside a character class, we keep the white space
+ if (charClass > 0) {
+ buffer.append((char)ch);
+ }
+ continue;
+ }
+
+ if (ch == '#') { // Skips chracters between '#' and a line end.
+ while (offset < len) {
+ ch = regex.charAt(offset++);
+ if (ch == '\r' || ch == '\n')
+ break;
+ }
+ continue;
+ }
+
+ int next; // Strips an escaped white space.
+ if (ch == '\\' && offset < len) {
+ if ((next = regex.charAt(offset)) == '#'
+ || next == '\t' || next == '\n' || next == '\f'
+ || next == '\r' || next == ' ') {
+ buffer.append((char)next);
+ offset ++;
+ } else { // Other escaped character.
+ buffer.append((char)'\\');
+ buffer.append((char)next);
+ offset ++;
+ }
+ }
+ else if (ch == '[') {
+ charClass++;
+ buffer.append((char)ch);
+ if (offset < len) {
+ next = regex.charAt(offset);
+ if (next == '[' || next ==']') {
+ buffer.append((char)next);
+ offset ++;
+ }
+ else if (next == '^' && offset + 1 < len) {
+ next = regex.charAt(offset + 1);
+ if (next == '[' || next ==']') {
+ buffer.append((char)'^');
+ buffer.append((char)next);
+ offset += 2;
+ }
+ }
+ }
+ }
+ else {
+ if (charClass > 0 && ch == ']') {
+ --charClass;
+ }
+ buffer.append((char)ch);
+ }
+ }
+ return buffer.toString();
+ }
+
+ // ================================================================
+
+ /**
+ * Sample entry.
+ * Usage: org.apache.xerces.utils.regex.REUtil <regex> <string>
+ */
+ public static void main(String[] argv) {
+ String pattern = null;
+ try {
+ String options = "";
+ String target = null;
+ if( argv.length == 0 ) {
+ System.out.println( "Error:Usage: java REUtil -i|-m|-s|-u|-w|-X regularExpression String" );
+ System.exit( 0 );
+ }
+ for (int i = 0; i < argv.length; i ++) {
+ if (argv[i].length() == 0 || argv[i].charAt(0) != '-') {
+ if (pattern == null)
+ pattern = argv[i];
+ else if (target == null)
+ target = argv[i];
+ else
+ System.err.println("Unnecessary: "+argv[i]);
+ } else if (argv[i].equals("-i")) {
+ options += "i";
+ } else if (argv[i].equals("-m")) {
+ options += "m";
+ } else if (argv[i].equals("-s")) {
+ options += "s";
+ } else if (argv[i].equals("-u")) {
+ options += "u";
+ } else if (argv[i].equals("-w")) {
+ options += "w";
+ } else if (argv[i].equals("-X")) {
+ options += "X";
+ } else {
+ System.err.println("Unknown option: "+argv[i]);
+ }
+ }
+ RegularExpression reg = new RegularExpression(pattern, options);
+ System.out.println("RegularExpression: "+reg);
+ Match match = new Match();
+ reg.matches(target, match);
+ for (int i = 0; i < match.getNumberOfGroups(); i ++) {
+ if (i == 0 ) System.out.print("Matched range for the whole pattern: ");
+ else System.out.print("["+i+"]: ");
+ if (match.getBeginning(i) < 0)
+ System.out.println("-1");
+ else {
+ System.out.print(match.getBeginning(i)+", "+match.getEnd(i)+", ");
+ System.out.println("\""+match.getCapturedText(i)+"\"");
+ }
+ }
+ } catch (ParseException pe) {
+ if (pattern == null) {
+ pe.printStackTrace();
+ } else {
+ System.err.println("org.apache.xerces.utils.regex.ParseException: "+pe.getMessage());
+ String indent = " ";
+ System.err.println(indent+pattern);
+ int loc = pe.getLocation();
+ if (loc >= 0) {
+ System.err.print(indent);
+ for (int i = 0; i < loc; i ++) System.err.print("-");
+ System.err.println("^");
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ static final int CACHESIZE = 20;
+ static final RegularExpression[] regexCache = new RegularExpression[CACHESIZE];
+ /**
+ * Creates a RegularExpression instance.
+ * This method caches created instances.
+ *
+ * @see RegularExpression#RegularExpression(java.lang.String, java.lang.String)
+ */
+ public static RegularExpression createRegex(String pattern, String options)
+ throws ParseException {
+ RegularExpression re = null;
+ int intOptions = REUtil.parseOptions(options);
+ synchronized (REUtil.regexCache) {
+ int i;
+ for (i = 0; i < REUtil.CACHESIZE; i ++) {
+ RegularExpression cached = REUtil.regexCache[i];
+ if (cached == null) {
+ i = -1;
+ break;
+ }
+ if (cached.equals(pattern, intOptions)) {
+ re = cached;
+ break;
+ }
+ }
+ if (re != null) {
+ if (i != 0) {
+ System.arraycopy(REUtil.regexCache, 0, REUtil.regexCache, 1, i);
+ REUtil.regexCache[0] = re;
+ }
+ } else {
+ re = new RegularExpression(pattern, options);
+ System.arraycopy(REUtil.regexCache, 0, REUtil.regexCache, 1, REUtil.CACHESIZE-1);
+ REUtil.regexCache[0] = re;
+ }
+ }
+ return re;
+ }
+
+ /**
+ *
+ * @see RegularExpression#matches(java.lang.String)
+ */
+ public static boolean matches(String regex, String target) throws ParseException {
+ return REUtil.createRegex(regex, null).matches(target);
+ }
+
+ /**
+ *
+ * @see RegularExpression#matches(java.lang.String)
+ */
+ public static boolean matches(String regex, String options, String target) throws ParseException {
+ return REUtil.createRegex(regex, options).matches(target);
+ }
+
+ // ================================================================
+
+ /**
+ *
+ */
+ public static String quoteMeta(String literal) {
+ int len = literal.length();
+ StringBuffer buffer = null;
+ for (int i = 0; i < len; i ++) {
+ int ch = literal.charAt(i);
+ if (".*+?{[()|\\^$".indexOf(ch) >= 0) {
+ if (buffer == null) {
+ buffer = new StringBuffer(i+(len-i)*2);
+ if (i > 0) buffer.append(literal.substring(0, i));
+ }
+ buffer.append((char)'\\');
+ buffer.append((char)ch);
+ } else if (buffer != null)
+ buffer.append((char)ch);
+ }
+ return buffer != null ? buffer.toString() : literal;
+ }
+
+ // ================================================================
+
+ static void dumpString(String v) {
+ for (int i = 0; i < v.length(); i ++) {
+ System.out.print(Integer.toHexString(v.charAt(i)));
+ System.out.print(" ");
+ }
+ System.out.println();
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/RangeToken.java b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/RangeToken.java
new file mode 100644
index 0000000..060eb6b
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/RangeToken.java
@@ -0,0 +1,623 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xpath.regex;
+
+/**
+ * This class represents a character class such as [a-z] or a period.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+final class RangeToken extends Token implements java.io.Serializable {
+
+ private static final long serialVersionUID = -553983121197679934L;
+
+ int[] ranges;
+ boolean sorted;
+ boolean compacted;
+ RangeToken icaseCache = null;
+ int[] map = null;
+ int nonMapIndex;
+
+ RangeToken(int type) {
+ super(type);
+ this.setSorted(false);
+ }
+
+ // for RANGE or NRANGE
+ protected void addRange(int start, int end) {
+ this.icaseCache = null;
+ //System.err.println("Token#addRange(): "+start+" "+end);
+ int r1, r2;
+ if (start <= end) {
+ r1 = start;
+ r2 = end;
+ } else {
+ r1 = end;
+ r2 = start;
+ }
+
+ int pos = 0;
+ if (this.ranges == null) {
+ this.ranges = new int[2];
+ this.ranges[0] = r1;
+ this.ranges[1] = r2;
+ this.setSorted(true);
+ } else {
+ pos = this.ranges.length;
+ if (this.ranges[pos-1]+1 == r1) {
+ this.ranges[pos-1] = r2;
+ return;
+ }
+ int[] temp = new int[pos+2];
+ System.arraycopy(this.ranges, 0, temp, 0, pos);
+ this.ranges = temp;
+ if (this.ranges[pos-1] >= r1)
+ this.setSorted(false);
+ this.ranges[pos++] = r1;
+ this.ranges[pos] = r2;
+ if (!this.sorted)
+ this.sortRanges();
+ }
+ }
+
+ private final boolean isSorted() {
+ return this.sorted;
+ }
+ private final void setSorted(boolean sort) {
+ this.sorted = sort;
+ if (!sort) this.compacted = false;
+ }
+ private final boolean isCompacted() {
+ return this.compacted;
+ }
+ private final void setCompacted() {
+ this.compacted = true;
+ }
+
+ protected void sortRanges() {
+ if (this.isSorted())
+ return;
+ if (this.ranges == null)
+ return;
+ //System.err.println("Do sorting: "+this.ranges.length);
+
+ // Bubble sort
+ // Why? -- In many cases,
+ // this.ranges has few elements.
+ for (int i = this.ranges.length-4; i >= 0; i -= 2) {
+ for (int j = 0; j <= i; j += 2) {
+ if (this.ranges[j] > this.ranges[j+2]
+ || this.ranges[j] == this.ranges[j+2] && this.ranges[j+1] > this.ranges[j+3]) {
+ int tmp;
+ tmp = this.ranges[j+2];
+ this.ranges[j+2] = this.ranges[j];
+ this.ranges[j] = tmp;
+ tmp = this.ranges[j+3];
+ this.ranges[j+3] = this.ranges[j+1];
+ this.ranges[j+1] = tmp;
+ }
+ }
+ }
+ this.setSorted(true);
+ }
+
+ /**
+ * this.ranges is sorted.
+ */
+ protected void compactRanges() {
+ boolean DEBUG = false;
+ if (this.ranges == null || this.ranges.length <= 2)
+ return;
+ if (this.isCompacted())
+ return;
+ int base = 0; // Index of writing point
+ int target = 0; // Index of processing point
+
+ while (target < this.ranges.length) {
+ if (base != target) {
+ this.ranges[base] = this.ranges[target++];
+ this.ranges[base+1] = this.ranges[target++];
+ } else
+ target += 2;
+ int baseend = this.ranges[base+1];
+ while (target < this.ranges.length) {
+ if (baseend+1 < this.ranges[target])
+ break;
+ if (baseend+1 == this.ranges[target]) {
+ if (DEBUG)
+ System.err.println("Token#compactRanges(): Compaction: ["+this.ranges[base]
+ +", "+this.ranges[base+1]
+ +"], ["+this.ranges[target]
+ +", "+this.ranges[target+1]
+ +"] -> ["+this.ranges[base]
+ +", "+this.ranges[target+1]
+ +"]");
+ this.ranges[base+1] = this.ranges[target+1];
+ baseend = this.ranges[base+1];
+ target += 2;
+ } else if (baseend >= this.ranges[target+1]) {
+ if (DEBUG)
+ System.err.println("Token#compactRanges(): Compaction: ["+this.ranges[base]
+ +", "+this.ranges[base+1]
+ +"], ["+this.ranges[target]
+ +", "+this.ranges[target+1]
+ +"] -> ["+this.ranges[base]
+ +", "+this.ranges[base+1]
+ +"]");
+ target += 2;
+ } else if (baseend < this.ranges[target+1]) {
+ if (DEBUG)
+ System.err.println("Token#compactRanges(): Compaction: ["+this.ranges[base]
+ +", "+this.ranges[base+1]
+ +"], ["+this.ranges[target]
+ +", "+this.ranges[target+1]
+ +"] -> ["+this.ranges[base]
+ +", "+this.ranges[target+1]
+ +"]");
+ this.ranges[base+1] = this.ranges[target+1];
+ baseend = this.ranges[base+1];
+ target += 2;
+ } else {
+ throw new RuntimeException("Token#compactRanges(): Internel Error: ["
+ +this.ranges[base]
+ +","+this.ranges[base+1]
+ +"] ["+this.ranges[target]
+ +","+this.ranges[target+1]+"]");
+ }
+ } // while
+ base += 2;
+ }
+
+ if (base != this.ranges.length) {
+ int[] result = new int[base];
+ System.arraycopy(this.ranges, 0, result, 0, base);
+ this.ranges = result;
+ }
+ this.setCompacted();
+ }
+
+ protected void mergeRanges(Token token) {
+ RangeToken tok = (RangeToken)token;
+ this.sortRanges();
+ tok.sortRanges();
+ if (tok.ranges == null)
+ return;
+ this.icaseCache = null;
+ this.setSorted(true);
+ if (this.ranges == null) {
+ this.ranges = new int[tok.ranges.length];
+ System.arraycopy(tok.ranges, 0, this.ranges, 0, tok.ranges.length);
+ return;
+ }
+ int[] result = new int[this.ranges.length+tok.ranges.length];
+ for (int i = 0, j = 0, k = 0; i < this.ranges.length || j < tok.ranges.length;) {
+ if (i >= this.ranges.length) {
+ result[k++] = tok.ranges[j++];
+ result[k++] = tok.ranges[j++];
+ } else if (j >= tok.ranges.length) {
+ result[k++] = this.ranges[i++];
+ result[k++] = this.ranges[i++];
+ } else if (tok.ranges[j] < this.ranges[i]
+ || tok.ranges[j] == this.ranges[i] && tok.ranges[j+1] < this.ranges[i+1]) {
+ result[k++] = tok.ranges[j++];
+ result[k++] = tok.ranges[j++];
+ } else {
+ result[k++] = this.ranges[i++];
+ result[k++] = this.ranges[i++];
+ }
+ }
+ this.ranges = result;
+ }
+
+ protected void subtractRanges(Token token) {
+ if (token.type == NRANGE) {
+ this.intersectRanges(token);
+ return;
+ }
+ RangeToken tok = (RangeToken)token;
+ if (tok.ranges == null || this.ranges == null)
+ return;
+ this.icaseCache = null;
+ this.sortRanges();
+ this.compactRanges();
+ tok.sortRanges();
+ tok.compactRanges();
+
+ //System.err.println("Token#substractRanges(): Entry: "+this.ranges.length+", "+tok.ranges.length);
+
+ int[] result = new int[this.ranges.length+tok.ranges.length];
+ int wp = 0, src = 0, sub = 0;
+ while (src < this.ranges.length && sub < tok.ranges.length) {
+ int srcbegin = this.ranges[src];
+ int srcend = this.ranges[src+1];
+ int subbegin = tok.ranges[sub];
+ int subend = tok.ranges[sub+1];
+ if (srcend < subbegin) { // Not overlapped
+ // src: o-----o
+ // sub: o-----o
+ // res: o-----o
+ // Reuse sub
+ result[wp++] = this.ranges[src++];
+ result[wp++] = this.ranges[src++];
+ } else if (srcend >= subbegin
+ && srcbegin <= subend) { // Overlapped
+ // src: o--------o
+ // sub: o----o
+ // sub: o----o
+ // sub: o----o
+ // sub: o------------o
+ if (subbegin <= srcbegin && srcend <= subend) {
+ // src: o--------o
+ // sub: o------------o
+ // res: empty
+ // Reuse sub
+ src += 2;
+ } else if (subbegin <= srcbegin) {
+ // src: o--------o
+ // sub: o----o
+ // res: o-----o
+ // Reuse src(=res)
+ this.ranges[src] = subend+1;
+ sub += 2;
+ } else if (srcend <= subend) {
+ // src: o--------o
+ // sub: o----o
+ // res: o-----o
+ // Reuse sub
+ result[wp++] = srcbegin;
+ result[wp++] = subbegin-1;
+ src += 2;
+ } else {
+ // src: o--------o
+ // sub: o----o
+ // res: o-o o-o
+ // Reuse src(=right res)
+ result[wp++] = srcbegin;
+ result[wp++] = subbegin-1;
+ this.ranges[src] = subend+1;
+ sub += 2;
+ }
+ } else if (subend < srcbegin) {
+ // Not overlapped
+ // src: o-----o
+ // sub: o----o
+ sub += 2;
+ } else {
+ throw new RuntimeException("Token#subtractRanges(): Internal Error: ["+this.ranges[src]
+ +","+this.ranges[src+1]
+ +"] - ["+tok.ranges[sub]
+ +","+tok.ranges[sub+1]
+ +"]");
+ }
+ }
+ while (src < this.ranges.length) {
+ result[wp++] = this.ranges[src++];
+ result[wp++] = this.ranges[src++];
+ }
+ this.ranges = new int[wp];
+ System.arraycopy(result, 0, this.ranges, 0, wp);
+ // this.ranges is sorted and compacted.
+ }
+
+ /**
+ * @param tok Ignore whether it is NRANGE or not.
+ */
+ protected void intersectRanges(Token token) {
+ RangeToken tok = (RangeToken)token;
+ if (tok.ranges == null || this.ranges == null)
+ return;
+ this.icaseCache = null;
+ this.sortRanges();
+ this.compactRanges();
+ tok.sortRanges();
+ tok.compactRanges();
+
+ int[] result = new int[this.ranges.length+tok.ranges.length];
+ int wp = 0, src1 = 0, src2 = 0;
+ while (src1 < this.ranges.length && src2 < tok.ranges.length) {
+ int src1begin = this.ranges[src1];
+ int src1end = this.ranges[src1+1];
+ int src2begin = tok.ranges[src2];
+ int src2end = tok.ranges[src2+1];
+ if (src1end < src2begin) { // Not overlapped
+ // src1: o-----o
+ // src2: o-----o
+ // res: empty
+ // Reuse src2
+ src1 += 2;
+ } else if (src1end >= src2begin
+ && src1begin <= src2end) { // Overlapped
+ // src1: o--------o
+ // src2: o----o
+ // src2: o----o
+ // src2: o----o
+ // src2: o------------o
+ if (src2begin <= src1begin && src1end <= src2end) {
+ // src1: o--------o
+ // src2: o------------o
+ // res: o--------o
+ // Reuse src2
+ result[wp++] = src1begin;
+ result[wp++] = src1end;
+ src1 += 2;
+ } else if (src2begin <= src1begin) {
+ // src1: o--------o
+ // src2: o----o
+ // res: o--o
+ // Reuse the rest of src1
+ result[wp++] = src1begin;
+ result[wp++] = src2end;
+ this.ranges[src1] = src2end+1;
+ src2 += 2;
+ } else if (src1end <= src2end) {
+ // src1: o--------o
+ // src2: o----o
+ // res: o--o
+ // Reuse src2
+ result[wp++] = src2begin;
+ result[wp++] = src1end;
+ src1 += 2;
+ } else {
+ // src1: o--------o
+ // src2: o----o
+ // res: o----o
+ // Reuse the rest of src1
+ result[wp++] = src2begin;
+ result[wp++] = src2end;
+ this.ranges[src1] = src2end+1;
+ }
+ } else if (src2end < src1begin) {
+ // Not overlapped
+ // src1: o-----o
+ // src2: o----o
+ src2 += 2;
+ } else {
+ throw new RuntimeException("Token#intersectRanges(): Internal Error: ["
+ +this.ranges[src1]
+ +","+this.ranges[src1+1]
+ +"] & ["+tok.ranges[src2]
+ +","+tok.ranges[src2+1]
+ +"]");
+ }
+ }
+ while (src1 < this.ranges.length) {
+ result[wp++] = this.ranges[src1++];
+ result[wp++] = this.ranges[src1++];
+ }
+ this.ranges = new int[wp];
+ System.arraycopy(result, 0, this.ranges, 0, wp);
+ // this.ranges is sorted and compacted.
+ }
+
+ /**
+ * for RANGE: Creates complement.
+ * for NRANGE: Creates the same meaning RANGE.
+ */
+ static Token complementRanges(Token token) {
+ if (token.type != RANGE && token.type != NRANGE)
+ throw new IllegalArgumentException("Token#complementRanges(): must be RANGE: "+token.type);
+ RangeToken tok = (RangeToken)token;
+ tok.sortRanges();
+ tok.compactRanges();
+ int len = tok.ranges.length+2;
+ if (tok.ranges[0] == 0)
+ len -= 2;
+ int last = tok.ranges[tok.ranges.length-1];
+ if (last == UTF16_MAX)
+ len -= 2;
+ RangeToken ret = Token.createRange();
+ ret.ranges = new int[len];
+ int wp = 0;
+ if (tok.ranges[0] > 0) {
+ ret.ranges[wp++] = 0;
+ ret.ranges[wp++] = tok.ranges[0]-1;
+ }
+ for (int i = 1; i < tok.ranges.length-2; i += 2) {
+ ret.ranges[wp++] = tok.ranges[i]+1;
+ ret.ranges[wp++] = tok.ranges[i+1]-1;
+ }
+ if (last != UTF16_MAX) {
+ ret.ranges[wp++] = last+1;
+ ret.ranges[wp] = UTF16_MAX;
+ }
+ ret.setCompacted();
+ return ret;
+ }
+
+ synchronized RangeToken getCaseInsensitiveToken() {
+ if (this.icaseCache != null)
+ return this.icaseCache;
+
+ RangeToken uppers = this.type == Token.RANGE ? Token.createRange() : Token.createNRange();
+ for (int i = 0; i < this.ranges.length; i += 2) {
+ for (int ch = this.ranges[i]; ch <= this.ranges[i+1]; ch ++) {
+ if (ch > 0xffff)
+ uppers.addRange(ch, ch);
+ else {
+ char uch = Character.toUpperCase((char)ch);
+ uppers.addRange(uch, uch);
+ }
+ }
+ }
+ RangeToken lowers = this.type == Token.RANGE ? Token.createRange() : Token.createNRange();
+ for (int i = 0; i < uppers.ranges.length; i += 2) {
+ for (int ch = uppers.ranges[i]; ch <= uppers.ranges[i+1]; ch ++) {
+ if (ch > 0xffff)
+ lowers.addRange(ch, ch);
+ else {
+ char uch = Character.toLowerCase((char)ch);
+ lowers.addRange(uch, uch);
+ }
+ }
+ }
+ lowers.mergeRanges(uppers);
+ lowers.mergeRanges(this);
+ lowers.compactRanges();
+
+ this.icaseCache = lowers;
+ return lowers;
+ }
+
+ void dumpRanges() {
+ System.err.print("RANGE: ");
+ if (this.ranges == null) {
+ System.err.println(" NULL");
+ return;
+ }
+ for (int i = 0; i < this.ranges.length; i += 2) {
+ System.err.print("["+this.ranges[i]+","+this.ranges[i+1]+"] ");
+ }
+ System.err.println("");
+ }
+
+ boolean match(int ch) {
+ if (this.map == null) this.createMap();
+ boolean ret;
+ if (this.type == RANGE) {
+ if (ch < MAPSIZE)
+ return (this.map[ch/32] & (1<<(ch&0x1f))) != 0;
+ ret = false;
+ for (int i = this.nonMapIndex; i < this.ranges.length; i += 2) {
+ if (this.ranges[i] <= ch && ch <= this.ranges[i+1])
+ return true;
+ }
+ } else {
+ if (ch < MAPSIZE)
+ return (this.map[ch/32] & (1<<(ch&0x1f))) == 0;
+ ret = true;
+ for (int i = this.nonMapIndex; i < this.ranges.length; i += 2) {
+ if (this.ranges[i] <= ch && ch <= this.ranges[i+1])
+ return false;
+ }
+ }
+ return ret;
+ }
+
+ private static final int MAPSIZE = 256;
+ private void createMap() {
+ int asize = MAPSIZE/32; // 32 is the number of bits in `int'.
+ int [] map = new int[asize];
+ int nonMapIndex = this.ranges.length;
+ for (int i = 0; i < asize; ++i) {
+ map[i] = 0;
+ }
+ for (int i = 0; i < this.ranges.length; i += 2) {
+ int s = this.ranges[i];
+ int e = this.ranges[i+1];
+ if (s < MAPSIZE) {
+ for (int j = s; j <= e && j < MAPSIZE; j++) {
+ map[j/32] |= 1<<(j&0x1f); // s&0x1f : 0-31
+ }
+ }
+ else {
+ nonMapIndex = i;
+ break;
+ }
+ if (e >= MAPSIZE) {
+ nonMapIndex = i;
+ break;
+ }
+ }
+ this.map = map;
+ this.nonMapIndex = nonMapIndex;
+ //for (int i = 0; i < asize; i ++) System.err.println("Map: "+Integer.toString(this.map[i], 16));
+ }
+
+ public String toString(int options) {
+ String ret;
+ if (this.type == RANGE) {
+ if (this == Token.token_dot)
+ ret = ".";
+ else if (this == Token.token_0to9)
+ ret = "\\d";
+ else if (this == Token.token_wordchars)
+ ret = "\\w";
+ else if (this == Token.token_spaces)
+ ret = "\\s";
+ else {
+ StringBuffer sb = new StringBuffer();
+ sb.append('[');
+ for (int i = 0; i < this.ranges.length; i += 2) {
+ if ((options & RegularExpression.SPECIAL_COMMA) != 0 && i > 0) sb.append(',');
+ if (this.ranges[i] == this.ranges[i+1]) {
+ sb.append(escapeCharInCharClass(this.ranges[i]));
+ } else {
+ sb.append(escapeCharInCharClass(this.ranges[i]));
+ sb.append((char)'-');
+ sb.append(escapeCharInCharClass(this.ranges[i+1]));
+ }
+ }
+ sb.append(']');
+ ret = sb.toString();
+ }
+ } else {
+ if (this == Token.token_not_0to9)
+ ret = "\\D";
+ else if (this == Token.token_not_wordchars)
+ ret = "\\W";
+ else if (this == Token.token_not_spaces)
+ ret = "\\S";
+ else {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[^");
+ for (int i = 0; i < this.ranges.length; i += 2) {
+ if ((options & RegularExpression.SPECIAL_COMMA) != 0 && i > 0) sb.append(',');
+ if (this.ranges[i] == this.ranges[i+1]) {
+ sb.append(escapeCharInCharClass(this.ranges[i]));
+ } else {
+ sb.append(escapeCharInCharClass(this.ranges[i]));
+ sb.append('-');
+ sb.append(escapeCharInCharClass(this.ranges[i+1]));
+ }
+ }
+ sb.append(']');
+ ret = sb.toString();
+ }
+ }
+ return ret;
+ }
+
+ private static String escapeCharInCharClass(int ch) {
+ String ret;
+ switch (ch) {
+ case '[': case ']': case '-': case '^':
+ case ',': case '\\':
+ ret = "\\"+(char)ch;
+ break;
+ case '\f': ret = "\\f"; break;
+ case '\n': ret = "\\n"; break;
+ case '\r': ret = "\\r"; break;
+ case '\t': ret = "\\t"; break;
+ case 0x1b: ret = "\\e"; break;
+ //case 0x0b: ret = "\\v"; break;
+ default:
+ if (ch < 0x20) {
+ String pre = "0"+Integer.toHexString(ch);
+ ret = "\\x"+pre.substring(pre.length()-2, pre.length());
+ } else if (ch >= 0x10000) {
+ String pre = "0"+Integer.toHexString(ch);
+ ret = "\\v"+pre.substring(pre.length()-6, pre.length());
+ } else
+ ret = ""+(char)ch;
+ }
+ return ret;
+ }
+
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/RegexParser.java b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/RegexParser.java
new file mode 100644
index 0000000..2da0e14
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/RegexParser.java
@@ -0,0 +1,1232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xpath.regex;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.Vector;
+
+/**
+ * A Regular Expression Parser.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+class RegexParser {
+ static final int T_CHAR = 0;
+ static final int T_EOF = 1;
+ static final int T_OR = 2; // '|'
+ static final int T_STAR = 3; // '*'
+ static final int T_PLUS = 4; // '+'
+ static final int T_QUESTION = 5; // '?'
+ static final int T_LPAREN = 6; // '('
+ static final int T_RPAREN = 7; // ')'
+ static final int T_DOT = 8; // '.'
+ static final int T_LBRACKET = 9; // '['
+ static final int T_BACKSOLIDUS = 10; // '\'
+ static final int T_CARET = 11; // '^'
+ static final int T_DOLLAR = 12; // '$'
+ static final int T_LPAREN2 = 13; // '(?:'
+ static final int T_LOOKAHEAD = 14; // '(?='
+ static final int T_NEGATIVELOOKAHEAD = 15; // '(?!'
+ static final int T_LOOKBEHIND = 16; // '(?<='
+ static final int T_NEGATIVELOOKBEHIND = 17; // '(?'
+ static final int T_SET_OPERATIONS = 19; // '(?['
+ static final int T_POSIX_CHARCLASS_START = 20; // '[:' in a character class
+ static final int T_COMMENT = 21; // '(?#'
+ static final int T_MODIFIERS = 22; // '(?' [\-,a-z,A-Z]
+ static final int T_CONDITION = 23; // '(?('
+ static final int T_XMLSCHEMA_CC_SUBTRACTION = 24; // '-[' in a character class
+
+ static class ReferencePosition {
+ int refNumber;
+ int position;
+ ReferencePosition(int n, int pos) {
+ this.refNumber = n;
+ this.position = pos;
+ }
+ }
+
+ int offset;
+ String regex;
+ int regexlen;
+ int options;
+ ResourceBundle resources;
+ int chardata;
+ int nexttoken;
+ static protected final int S_NORMAL = 0;
+ static protected final int S_INBRACKETS = 1;
+ static protected final int S_INXBRACKETS = 2;
+ int context = S_NORMAL;
+ int parenOpened = 1;
+ int parennumber = 1;
+ boolean hasBackReferences;
+ Vector references = null;
+
+ public RegexParser() {
+ this.setLocale(Locale.getDefault());
+ }
+ public RegexParser(Locale locale) {
+ this.setLocale(locale);
+ }
+
+ public void setLocale(Locale locale) {
+ try {
+ if (locale != null) {
+ this.resources = ResourceBundle.getBundle("org.apache.xerces.impl.xpath.regex.message", locale);
+ }
+ else {
+ this.resources = ResourceBundle.getBundle("org.apache.xerces.impl.xpath.regex.message");
+ }
+ }
+ catch (MissingResourceException mre) {
+ throw new RuntimeException("Installation Problem??? Couldn't load messages: "
+ + mre.getMessage());
+ }
+ }
+
+ final ParseException ex(String key, int loc) {
+ return new ParseException(this.resources.getString(key), loc);
+ }
+
+ protected final boolean isSet(int flag) {
+ return (this.options & flag) == flag;
+ }
+
+ synchronized Token parse(String regex, int options) throws ParseException {
+ this.options = options;
+ this.offset = 0;
+ this.setContext(S_NORMAL);
+ this.parennumber = 1;
+ this.parenOpened = 1;
+ this.hasBackReferences = false;
+ this.regex = regex;
+ if (this.isSet(RegularExpression.EXTENDED_COMMENT))
+ this.regex = REUtil.stripExtendedComment(this.regex);
+ this.regexlen = this.regex.length();
+
+
+ this.next();
+ Token ret = this.parseRegex();
+ if (this.offset != this.regexlen)
+ throw ex("parser.parse.1", this.offset);
+ if (this.read() != T_EOF) {
+ throw ex("parser.parse.1", this.offset-1);
+ }
+ if (this.references != null) {
+ for (int i = 0; i < this.references.size(); i ++) {
+ ReferencePosition position = (ReferencePosition)this.references.elementAt(i);
+ if (this.parennumber <= position.refNumber)
+ throw ex("parser.parse.2", position.position);
+ }
+ this.references.removeAllElements();
+ }
+ return ret;
+ }
+
+ /*
+ public RegularExpression createRegex(String regex, int options) throws ParseException {
+ Token tok = this.parse(regex, options);
+ return new RegularExpression(regex, tok, this.parennumber, this.hasBackReferences, options);
+ }
+ */
+
+ protected final void setContext(int con) {
+ this.context = con;
+ }
+
+ final int read() {
+ return this.nexttoken;
+ }
+
+ final void next() {
+ if (this.offset >= this.regexlen) {
+ this.chardata = -1;
+ this.nexttoken = T_EOF;
+ return;
+ }
+
+ int ret;
+ int ch = this.regex.charAt(this.offset++);
+ this.chardata = ch;
+
+ if (this.context == S_INBRACKETS) {
+ // In a character class, this.chardata has one character, that is to say,
+ // a pair of surrogates is composed and stored to this.chardata.
+ switch (ch) {
+ case '\\':
+ ret = T_BACKSOLIDUS;
+ if (this.offset >= this.regexlen)
+ throw ex("parser.next.1", this.offset-1);
+ this.chardata = this.regex.charAt(this.offset++);
+ break;
+
+ case '-':
+ // Allow character class subtraction (regardless of whether we are in
+ // XML Schema mode or not)
+ if (this.offset < this.regexlen && this.regex.charAt(this.offset) == '[') {
+ this.offset++;
+ ret = T_XMLSCHEMA_CC_SUBTRACTION;
+ } else
+ ret = T_CHAR;
+ break;
+
+ case '[':
+ if (!this.isSet(RegularExpression.XMLSCHEMA_MODE)
+ && this.offset < this.regexlen && this.regex.charAt(this.offset) == ':') {
+ this.offset++;
+ ret = T_POSIX_CHARCLASS_START;
+ break;
+ } // Through down
+ default:
+ if (REUtil.isHighSurrogate(ch) && this.offset < this.regexlen) {
+ int low = this.regex.charAt(this.offset);
+ if (REUtil.isLowSurrogate(low)) {
+ this.chardata = REUtil.composeFromSurrogates(ch, low);
+ this.offset ++;
+ }
+ }
+ ret = T_CHAR;
+ }
+ this.nexttoken = ret;
+ return;
+ }
+
+ switch (ch) {
+ case '|': ret = T_OR; break;
+ case '*': ret = T_STAR; break;
+ case '+': ret = T_PLUS; break;
+ case '?': ret = T_QUESTION; break;
+ case ')': ret = T_RPAREN; break;
+ case '.': ret = T_DOT; break;
+ case '[': ret = T_LBRACKET; break;
+ case '^':
+ if (this.isSet(RegularExpression.XMLSCHEMA_MODE)) {
+ ret = T_CHAR;
+ }
+ else {
+ ret = T_CARET;
+ }
+ break;
+ case '$':
+ if (this.isSet(RegularExpression.XMLSCHEMA_MODE)) {
+ ret = T_CHAR;
+ }
+ else {
+ ret = T_DOLLAR;
+ }
+ break;
+ case '(':
+ ret = T_LPAREN;
+ if (this.offset >= this.regexlen)
+ break;
+ if (this.regex.charAt(this.offset) != '?')
+ break;
+ if (++this.offset >= this.regexlen)
+ throw ex("parser.next.2", this.offset-1);
+ ch = this.regex.charAt(this.offset++);
+ switch (ch) {
+ case ':': ret = T_LPAREN2; break;
+ case '=': ret = T_LOOKAHEAD; break;
+ case '!': ret = T_NEGATIVELOOKAHEAD; break;
+ case '[': ret = T_SET_OPERATIONS; break;
+ case '>': ret = T_INDEPENDENT; break;
+ case '<':
+ if (this.offset >= this.regexlen)
+ throw ex("parser.next.2", this.offset-3);
+ ch = this.regex.charAt(this.offset++);
+ if (ch == '=') {
+ ret = T_LOOKBEHIND;
+ } else if (ch == '!') {
+ ret = T_NEGATIVELOOKBEHIND;
+ } else
+ throw ex("parser.next.3", this.offset-3);
+ break;
+ case '#':
+ while (this.offset < this.regexlen) {
+ ch = this.regex.charAt(this.offset++);
+ if (ch == ')') break;
+ }
+ if (ch != ')')
+ throw ex("parser.next.4", this.offset-1);
+ ret = T_COMMENT;
+ break;
+ default:
+ if (ch == '-' || 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z') {// Options
+ this.offset --;
+ ret = T_MODIFIERS;
+ break;
+ } else if (ch == '(') { // conditional
+ ret = T_CONDITION; // this.offsets points the next of '('.
+ break;
+ }
+ throw ex("parser.next.2", this.offset-2);
+ }
+ break;
+
+ case '\\':
+ ret = T_BACKSOLIDUS;
+ if (this.offset >= this.regexlen)
+ throw ex("parser.next.1", this.offset-1);
+ this.chardata = this.regex.charAt(this.offset++);
+ break;
+
+ default:
+ ret = T_CHAR;
+ }
+ this.nexttoken = ret;
+ }
+
+ /**
+ * regex ::= term (`|` term)*
+ * term ::= factor+
+ * factor ::= ('^' | '$' | '\A' | '\Z' | '\z' | '\b' | '\B' | '\<' | '\>'
+ * | atom (('*' | '+' | '?' | minmax ) '?'? )?)
+ * | '(?=' regex ')' | '(?!' regex ')' | '(?<=' regex ')' | '(?<!' regex ')'
+ * atom ::= char | '.' | range | '(' regex ')' | '(?:' regex ')' | '\' [0-9]
+ * | '\w' | '\W' | '\d' | '\D' | '\s' | '\S' | category-block
+ */
+ Token parseRegex() throws ParseException {
+ Token tok = this.parseTerm();
+ Token parent = null;
+ while (this.read() == T_OR) {
+ this.next(); // '|'
+ if (parent == null) {
+ parent = Token.createUnion();
+ parent.addChild(tok);
+ tok = parent;
+ }
+ tok.addChild(this.parseTerm());
+ }
+ return tok;
+ }
+
+ /**
+ * term ::= factor+
+ */
+ Token parseTerm() throws ParseException {
+ int ch = this.read();
+ if (ch == T_OR || ch == T_RPAREN || ch == T_EOF) {
+ return Token.createEmpty();
+ } else {
+ Token tok = this.parseFactor();
+ Token concat = null;
+ while ((ch = this.read()) != T_OR && ch != T_RPAREN && ch != T_EOF) {
+ if (concat == null) {
+ concat = Token.createConcat();
+ concat.addChild(tok);
+ tok = concat;
+ }
+ concat.addChild(this.parseFactor());
+ //tok = Token.createConcat(tok, this.parseFactor());
+ }
+ return tok;
+ }
+ }
+
+ // ----------------------------------------------------------------
+
+ Token processCaret() throws ParseException {
+ this.next();
+ return Token.token_linebeginning;
+ }
+ Token processDollar() throws ParseException {
+ this.next();
+ return Token.token_lineend;
+ }
+ Token processLookahead() throws ParseException {
+ this.next();
+ Token tok = Token.createLook(Token.LOOKAHEAD, this.parseRegex());
+ if (this.read() != T_RPAREN) throw ex("parser.factor.1", this.offset-1);
+ this.next(); // ')'
+ return tok;
+ }
+ Token processNegativelookahead() throws ParseException {
+ this.next();
+ Token tok = Token.createLook(Token.NEGATIVELOOKAHEAD, this.parseRegex());
+ if (this.read() != T_RPAREN) throw ex("parser.factor.1", this.offset-1);
+ this.next(); // ')'
+ return tok;
+ }
+ Token processLookbehind() throws ParseException {
+ this.next();
+ Token tok = Token.createLook(Token.LOOKBEHIND, this.parseRegex());
+ if (this.read() != T_RPAREN) throw ex("parser.factor.1", this.offset-1);
+ this.next(); // ')'
+ return tok;
+ }
+ Token processNegativelookbehind() throws ParseException {
+ this.next();
+ Token tok = Token.createLook(Token.NEGATIVELOOKBEHIND, this.parseRegex());
+ if (this.read() != T_RPAREN) throw ex("parser.factor.1", this.offset-1);
+ this.next(); // ')'
+ return tok;
+ }
+ Token processBacksolidus_A() throws ParseException {
+ this.next();
+ return Token.token_stringbeginning;
+ }
+ Token processBacksolidus_Z() throws ParseException {
+ this.next();
+ return Token.token_stringend2;
+ }
+ Token processBacksolidus_z() throws ParseException {
+ this.next();
+ return Token.token_stringend;
+ }
+ Token processBacksolidus_b() throws ParseException {
+ this.next();
+ return Token.token_wordedge;
+ }
+ Token processBacksolidus_B() throws ParseException {
+ this.next();
+ return Token.token_not_wordedge;
+ }
+ Token processBacksolidus_lt() throws ParseException {
+ this.next();
+ return Token.token_wordbeginning;
+ }
+ Token processBacksolidus_gt() throws ParseException {
+ this.next();
+ return Token.token_wordend;
+ }
+ Token processStar(Token tok) throws ParseException {
+ this.next();
+ if (this.read() == T_QUESTION) {
+ this.next();
+ return Token.createNGClosure(tok);
+ } else
+ return Token.createClosure(tok);
+ }
+ Token processPlus(Token tok) throws ParseException {
+ // X+ -> XX*
+ this.next();
+ if (this.read() == T_QUESTION) {
+ this.next();
+ return Token.createConcat(tok, Token.createNGClosure(tok));
+ } else
+ return Token.createConcat(tok, Token.createClosure(tok));
+ }
+ Token processQuestion(Token tok) throws ParseException {
+ // X? -> X|
+ this.next();
+ Token par = Token.createUnion();
+ if (this.read() == T_QUESTION) {
+ this.next();
+ par.addChild(Token.createEmpty());
+ par.addChild(tok);
+ } else {
+ par.addChild(tok);
+ par.addChild(Token.createEmpty());
+ }
+ return par;
+ }
+ boolean checkQuestion(int off) {
+ return off < this.regexlen && this.regex.charAt(off) == '?';
+ }
+ Token processParen() throws ParseException {
+ this.next();
+ int p = this.parenOpened++;
+ Token tok = Token.createParen(this.parseRegex(), p);
+ if (this.read() != T_RPAREN) throw ex("parser.factor.1", this.offset-1);
+ this.parennumber++;
+ this.next(); // Skips ')'
+ return tok;
+ }
+ Token processParen2() throws ParseException {
+ this.next();
+ Token tok = Token.createParen(this.parseRegex(), 0);
+ if (this.read() != T_RPAREN) throw ex("parser.factor.1", this.offset-1);
+ this.next(); // Skips ')'
+ return tok;
+ }
+ Token processCondition() throws ParseException {
+ // this.offset points the next of '('
+ if (this.offset+1 >= this.regexlen) throw ex("parser.factor.4", this.offset);
+ // Parses a condition.
+ int refno = -1;
+ Token condition = null;
+ int ch = this.regex.charAt(this.offset);
+ if ('1' <= ch && ch <= '9') {
+ refno = ch-'0';
+ int finalRefno = refno;
+
+ if (this.parennumber <= refno)
+ throw ex("parser.parse.2", this.offset);
+
+ while (this.offset + 1 < this.regexlen) {
+ ch = this.regex.charAt(this.offset + 1);
+ if ('0' <= ch && ch <= '9') {
+ refno = (refno * 10) + (ch - '0');
+ if (refno < this.parennumber) {
+ finalRefno= refno;
+ ++this.offset;
+ }
+ else {
+ break;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ this.hasBackReferences = true;
+ if (this.references == null) this.references = new Vector();
+ this.references.addElement(new ReferencePosition(finalRefno, this.offset));
+ this.offset ++;
+ if (this.regex.charAt(this.offset) != ')') throw ex("parser.factor.1", this.offset);
+ this.offset ++;
+ } else {
+ if (ch == '?') this.offset --; // Points '('.
+ this.next();
+ condition = this.parseFactor();
+ switch (condition.type) {
+ case Token.LOOKAHEAD:
+ case Token.NEGATIVELOOKAHEAD:
+ case Token.LOOKBEHIND:
+ case Token.NEGATIVELOOKBEHIND:
+ break;
+ case Token.ANCHOR:
+ if (this.read() != T_RPAREN) throw ex("parser.factor.1", this.offset-1);
+ break;
+ default:
+ throw ex("parser.factor.5", this.offset);
+ }
+ }
+ // Parses yes/no-patterns.
+ this.next();
+ Token yesPattern = this.parseRegex();
+ Token noPattern = null;
+ if (yesPattern.type == Token.UNION) {
+ if (yesPattern.size() != 2) throw ex("parser.factor.6", this.offset);
+ noPattern = yesPattern.getChild(1);
+ yesPattern = yesPattern.getChild(0);
+ }
+ if (this.read() != T_RPAREN) throw ex("parser.factor.1", this.offset-1);
+ this.next();
+ return Token.createCondition(refno, condition, yesPattern, noPattern);
+ }
+ Token processModifiers() throws ParseException {
+ // this.offset points the next of '?'.
+ // modifiers ::= [imsw]* ('-' [imsw]*)? ':'
+ int add = 0, mask = 0, ch = -1;
+ while (this.offset < this.regexlen) {
+ ch = this.regex.charAt(this.offset);
+ int v = REUtil.getOptionValue(ch);
+ if (v == 0) break; // '-' or ':'?
+ add |= v;
+ this.offset ++;
+ }
+ if (this.offset >= this.regexlen) throw ex("parser.factor.2", this.offset-1);
+ if (ch == '-') {
+ this.offset ++;
+ while (this.offset < this.regexlen) {
+ ch = this.regex.charAt(this.offset);
+ int v = REUtil.getOptionValue(ch);
+ if (v == 0) break; // ':'?
+ mask |= v;
+ this.offset ++;
+ }
+ if (this.offset >= this.regexlen) throw ex("parser.factor.2", this.offset-1);
+ }
+ Token tok;
+ if (ch == ':') {
+ this.offset ++;
+ this.next();
+ tok = Token.createModifierGroup(this.parseRegex(), add, mask);
+ if (this.read() != T_RPAREN) throw ex("parser.factor.1", this.offset-1);
+ this.next();
+ } else if (ch == ')') { // such as (?-i)
+ this.offset ++;
+ this.next();
+ tok = Token.createModifierGroup(this.parseRegex(), add, mask);
+ } else
+ throw ex("parser.factor.3", this.offset);
+
+ return tok;
+ }
+ Token processIndependent() throws ParseException {
+ this.next();
+ Token tok = Token.createLook(Token.INDEPENDENT, this.parseRegex());
+ if (this.read() != T_RPAREN) throw ex("parser.factor.1", this.offset-1);
+ this.next(); // Skips ')'
+ return tok;
+ }
+ Token processBacksolidus_c() throws ParseException {
+ int ch2; // Must be in 0x0040-0x005f
+ if (this.offset >= this.regexlen
+ || ((ch2 = this.regex.charAt(this.offset++)) & 0xffe0) != 0x0040)
+ throw ex("parser.atom.1", this.offset-1);
+ this.next();
+ return Token.createChar(ch2-0x40);
+ }
+ Token processBacksolidus_C() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processBacksolidus_i() throws ParseException {
+ Token tok = Token.createChar('i');
+ this.next();
+ return tok;
+ }
+ Token processBacksolidus_I() throws ParseException {
+ throw ex("parser.process.1", this.offset);
+ }
+ Token processBacksolidus_g() throws ParseException {
+ this.next();
+ return Token.getGraphemePattern();
+ }
+ Token processBacksolidus_X() throws ParseException {
+ this.next();
+ return Token.getCombiningCharacterSequence();
+ }
+ Token processBackreference() throws ParseException {
+ int refnum = this.chardata-'0';
+ int finalRefnum = refnum;
+
+ if (this.parennumber <= refnum)
+ throw ex("parser.parse.2", this.offset-2);
+
+ while (this.offset < this.regexlen) {
+ final int ch = this.regex.charAt(this.offset);
+ if ('0' <= ch && ch <= '9') {
+ refnum = (refnum * 10) + (ch - '0');
+ if (refnum < this.parennumber) {
+ ++this.offset;
+ finalRefnum = refnum;
+ this.chardata = ch;
+ }
+ else {
+ break;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ Token tok = Token.createBackReference(finalRefnum);
+ this.hasBackReferences = true;
+ if (this.references == null) this.references = new Vector();
+ this.references.addElement(new ReferencePosition(finalRefnum, this.offset-2));
+ this.next();
+ return tok;
+ }
+
+ // ----------------------------------------------------------------
+
+ /**
+ * factor ::= ('^' | '$' | '\A' | '\Z' | '\z' | '\b' | '\B' | '\<' | '\>'
+ * | atom (('*' | '+' | '?' | minmax ) '?'? )?)
+ * | '(?=' regex ')' | '(?!' regex ')' | '(?<=' regex ')' | '(?<!' regex ')'
+ * | '(?#' [^)]* ')'
+ * minmax ::= '{' min (',' max?)? '}'
+ * min ::= [0-9]+
+ * max ::= [0-9]+
+ */
+ Token parseFactor() throws ParseException {
+ int ch = this.read();
+ Token tok;
+ switch (ch) {
+ case T_CARET: return this.processCaret();
+ case T_DOLLAR: return this.processDollar();
+ case T_LOOKAHEAD: return this.processLookahead();
+ case T_NEGATIVELOOKAHEAD: return this.processNegativelookahead();
+ case T_LOOKBEHIND: return this.processLookbehind();
+ case T_NEGATIVELOOKBEHIND: return this.processNegativelookbehind();
+
+ case T_COMMENT:
+ this.next();
+ return Token.createEmpty();
+
+ case T_BACKSOLIDUS:
+ switch (this.chardata) {
+ case 'A': return this.processBacksolidus_A();
+ case 'Z': return this.processBacksolidus_Z();
+ case 'z': return this.processBacksolidus_z();
+ case 'b': return this.processBacksolidus_b();
+ case 'B': return this.processBacksolidus_B();
+ case '<': return this.processBacksolidus_lt();
+ case '>': return this.processBacksolidus_gt();
+ }
+ // through down
+ }
+ tok = this.parseAtom();
+ ch = this.read();
+ switch (ch) {
+ case T_STAR: return this.processStar(tok);
+ case T_PLUS: return this.processPlus(tok);
+ case T_QUESTION: return this.processQuestion(tok);
+ case T_CHAR:
+ if (this.chardata == '{' && this.offset < this.regexlen) {
+
+ int off = this.offset; // this.offset -> next of '{'
+ int min = 0, max = -1;
+
+ if ((ch = this.regex.charAt(off++)) >= '0' && ch <= '9') {
+
+ min = ch -'0';
+ while (off < this.regexlen
+ && (ch = this.regex.charAt(off++)) >= '0' && ch <= '9') {
+ min = min*10 +ch-'0';
+ if (min < 0)
+ throw ex("parser.quantifier.5", this.offset);
+ }
+ }
+ else {
+ throw ex("parser.quantifier.1", this.offset);
+ }
+
+ max = min;
+ if (ch == ',') {
+
+ if (off >= this.regexlen) {
+ throw ex("parser.quantifier.3", this.offset);
+ }
+ else if ((ch = this.regex.charAt(off++)) >= '0' && ch <= '9') {
+
+ max = ch -'0'; // {min,max}
+ while (off < this.regexlen
+ && (ch = this.regex.charAt(off++)) >= '0'
+ && ch <= '9') {
+ max = max*10 +ch-'0';
+ if (max < 0)
+ throw ex("parser.quantifier.5", this.offset);
+ }
+
+ if (min > max)
+ throw ex("parser.quantifier.4", this.offset);
+ }
+ else { // assume {min,}
+ max = -1;
+ }
+ }
+
+ if (ch != '}')
+ throw ex("parser.quantifier.2", this.offset);
+
+ if (this.checkQuestion(off)) { // off -> next of '}'
+ tok = Token.createNGClosure(tok);
+ this.offset = off+1;
+ } else {
+ tok = Token.createClosure(tok);
+ this.offset = off;
+ }
+
+ tok.setMin(min);
+ tok.setMax(max);
+ //System.err.println("CLOSURE: "+min+", "+max);
+ this.next();
+ }
+ }
+ return tok;
+ }
+
+ /**
+ * atom ::= char | '.' | char-class | '(' regex ')' | '(?:' regex ')' | '\' [0-9]
+ * | '\w' | '\W' | '\d' | '\D' | '\s' | '\S' | category-block
+ * | '(?>' regex ')'
+ * char ::= '\\' | '\' [efnrt] | bmp-code | character-1
+ */
+ Token parseAtom() throws ParseException {
+ int ch = this.read();
+ Token tok = null;
+ switch (ch) {
+ case T_LPAREN: return this.processParen();
+ case T_LPAREN2: return this.processParen2(); // '(?:'
+ case T_CONDITION: return this.processCondition(); // '(?('
+ case T_MODIFIERS: return this.processModifiers(); // (?modifiers ... )
+ case T_INDEPENDENT: return this.processIndependent();
+ case T_DOT:
+ this.next(); // Skips '.'
+ tok = Token.token_dot;
+ break;
+
+ /**
+ * char-class ::= '[' ( '^'? range ','?)+ ']'
+ * range ::= '\d' | '\w' | '\s' | category-block | range-char
+ * | range-char '-' range-char
+ * range-char ::= '\[' | '\]' | '\\' | '\' [,-efnrtv] | bmp-code | character-2
+ * bmp-char ::= '\' 'u' [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]
+ */
+ case T_LBRACKET: return this.parseCharacterClass(true);
+ case T_SET_OPERATIONS: return this.parseSetOperations();
+
+ case T_BACKSOLIDUS:
+ switch (this.chardata) {
+ case 'd': case 'D':
+ case 'w': case 'W':
+ case 's': case 'S':
+ tok = this.getTokenForShorthand(this.chardata);
+ this.next();
+ return tok;
+
+ case 'e': case 'f': case 'n': case 'r':
+ case 't': case 'u': case 'v': case 'x':
+ {
+ int ch2 = this.decodeEscaped();
+ if (ch2 < 0x10000) {
+ tok = Token.createChar(ch2);
+ } else {
+ tok = Token.createString(REUtil.decomposeToSurrogates(ch2));
+ }
+ }
+ break;
+
+ case 'c': return this.processBacksolidus_c();
+ case 'C': return this.processBacksolidus_C();
+ case 'i': return this.processBacksolidus_i();
+ case 'I': return this.processBacksolidus_I();
+ case 'g': return this.processBacksolidus_g();
+ case 'X': return this.processBacksolidus_X();
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ return this.processBackreference();
+
+ case 'P':
+ case 'p':
+ int pstart = this.offset;
+ tok = processBacksolidus_pP(this.chardata);
+ if (tok == null) throw this.ex("parser.atom.5", pstart);
+ break;
+
+ default:
+ tok = Token.createChar(this.chardata);
+ }
+ this.next();
+ break;
+
+ case T_CHAR:
+ if (this.chardata == ']' || this.chardata == '{' || this.chardata == '}')
+ throw this.ex("parser.atom.4", this.offset-1);
+ tok = Token.createChar(this.chardata);
+ int high = this.chardata;
+ this.next();
+ if (REUtil.isHighSurrogate(high)
+ && this.read() == T_CHAR && REUtil.isLowSurrogate(this.chardata)) {
+ char[] sur = new char[2];
+ sur[0] = (char)high;
+ sur[1] = (char)this.chardata;
+ tok = Token.createParen(Token.createString(new String(sur)), 0);
+ this.next();
+ }
+ break;
+
+ default:
+ throw this.ex("parser.atom.4", this.offset-1);
+ }
+ return tok;
+ }
+
+ protected RangeToken processBacksolidus_pP(int c) throws ParseException {
+
+ this.next();
+ if (this.read() != T_CHAR || this.chardata != '{')
+ throw this.ex("parser.atom.2", this.offset-1);
+
+ // handle category escape
+ boolean positive = c == 'p';
+ int namestart = this.offset;
+ int nameend = this.regex.indexOf('}', namestart);
+
+ if (nameend < 0)
+ throw this.ex("parser.atom.3", this.offset);
+
+ String pname = this.regex.substring(namestart, nameend);
+ this.offset = nameend+1;
+
+ return Token.getRange(pname, positive, this.isSet(RegularExpression.XMLSCHEMA_MODE));
+ }
+
+ int processCIinCharacterClass(RangeToken tok, int c) {
+ return this.decodeEscaped();
+ }
+
+ /**
+ * char-class ::= '[' ( '^'? range ','?)+ ']'
+ * range ::= '\d' | '\w' | '\s' | category-block | range-char
+ * | range-char '-' range-char
+ * range-char ::= '\[' | '\]' | '\\' | '\' [,-efnrtv] | bmp-code | character-2
+ * bmp-code ::= '\' 'u' [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]
+ */
+ protected RangeToken parseCharacterClass(boolean useNrange) throws ParseException {
+ this.setContext(S_INBRACKETS);
+ this.next(); // '['
+ boolean nrange = false;
+ RangeToken base = null;
+ RangeToken tok;
+ if (this.read() == T_CHAR && this.chardata == '^') {
+ nrange = true;
+ this.next(); // '^'
+ if (useNrange) {
+ tok = Token.createNRange();
+ } else {
+ base = Token.createRange();
+ base.addRange(0, Token.UTF16_MAX);
+ tok = Token.createRange();
+ }
+ } else {
+ tok = Token.createRange();
+ }
+ int type;
+ boolean firstloop = true;
+ while ((type = this.read()) != T_EOF) {
+ if (type == T_CHAR && this.chardata == ']' && !firstloop)
+ break;
+ int c = this.chardata;
+ boolean end = false;
+ if (type == T_BACKSOLIDUS) {
+ switch (c) {
+ case 'd': case 'D':
+ case 'w': case 'W':
+ case 's': case 'S':
+ tok.mergeRanges(this.getTokenForShorthand(c));
+ end = true;
+ break;
+
+ case 'i': case 'I':
+ case 'c': case 'C':
+ c = this.processCIinCharacterClass(tok, c);
+ if (c < 0) end = true;
+ break;
+
+ case 'p':
+ case 'P':
+ int pstart = this.offset;
+ RangeToken tok2 = this.processBacksolidus_pP(c);
+ if (tok2 == null) throw this.ex("parser.atom.5", pstart);
+ tok.mergeRanges(tok2);
+ end = true;
+ break;
+
+ default:
+ c = this.decodeEscaped();
+ } // \ + c
+ } // backsolidus
+ // POSIX Character class such as [:alnum:]
+ else if (type == T_POSIX_CHARCLASS_START) {
+ int nameend = this.regex.indexOf(':', this.offset);
+ if (nameend < 0) throw this.ex("parser.cc.1", this.offset);
+ boolean positive = true;
+ if (this.regex.charAt(this.offset) == '^') {
+ this.offset ++;
+ positive = false;
+ }
+ String name = this.regex.substring(this.offset, nameend);
+ RangeToken range = Token.getRange(name, positive,
+ this.isSet(RegularExpression.XMLSCHEMA_MODE));
+ if (range == null) throw this.ex("parser.cc.3", this.offset);
+ tok.mergeRanges(range);
+ end = true;
+ if (nameend+1 >= this.regexlen || this.regex.charAt(nameend+1) != ']')
+ throw this.ex("parser.cc.1", nameend);
+ this.offset = nameend+2;
+ }
+ else if (type == T_XMLSCHEMA_CC_SUBTRACTION && !firstloop) {
+ if (nrange) {
+ nrange = false;
+ if (useNrange) {
+ tok = (RangeToken) Token.complementRanges(tok);
+ }
+ else {
+ base.subtractRanges(tok);
+ tok = base;
+ }
+ }
+ RangeToken range2 = this.parseCharacterClass(false);
+ tok.subtractRanges(range2);
+ if (this.read() != T_CHAR || this.chardata != ']') {
+ throw this.ex("parser.cc.5", this.offset);
+ }
+ break; // Exit this loop
+ }
+ this.next();
+ if (!end) { // if not shorthands...
+ if (this.read() != T_CHAR || this.chardata != '-') { // Here is no '-'.
+ if (!this.isSet(RegularExpression.IGNORE_CASE) || c > 0xffff) {
+ tok.addRange(c, c);
+ }
+ else {
+ addCaseInsensitiveChar(tok, c);
+ }
+ }
+ else if (type == T_XMLSCHEMA_CC_SUBTRACTION) {
+ throw this.ex("parser.cc.8", this.offset-1);
+ }
+ else {
+ this.next(); // Skips '-'
+ if ((type = this.read()) == T_EOF) throw this.ex("parser.cc.2", this.offset);
+ if (type == T_CHAR && this.chardata == ']') {
+ if (!this.isSet(RegularExpression.IGNORE_CASE) || c > 0xffff) {
+ tok.addRange(c, c);
+ }
+ else {
+ addCaseInsensitiveChar(tok, c);
+ }
+ tok.addRange('-', '-');
+ } else {
+ int rangeend = this.chardata;
+ if (type == T_BACKSOLIDUS) {
+ rangeend = this.decodeEscaped();
+ }
+ this.next();
+ if (c > rangeend) {
+ throw this.ex("parser.ope.3", this.offset-1);
+ }
+ if (!this.isSet(RegularExpression.IGNORE_CASE) ||
+ (c > 0xffff && rangeend > 0xffff)) {
+ tok.addRange(c, rangeend);
+ }
+ else {
+ addCaseInsensitiveCharRange(tok, c, rangeend);
+ }
+ }
+ }
+ }
+ if (this.isSet(RegularExpression.SPECIAL_COMMA)
+ && this.read() == T_CHAR && this.chardata == ',') {
+ this.next();
+ }
+ firstloop = false;
+ }
+ if (this.read() == T_EOF) {
+ throw this.ex("parser.cc.2", this.offset);
+ }
+
+ if (!useNrange && nrange) {
+ base.subtractRanges(tok);
+ tok = base;
+ }
+ tok.sortRanges();
+ tok.compactRanges();
+ this.setContext(S_NORMAL);
+ this.next(); // Skips ']'
+
+ return tok;
+ }
+
+ /**
+ * '(?[' ... ']' (('-' | '+' | '&') '[' ... ']')? ')'
+ */
+ protected RangeToken parseSetOperations() throws ParseException {
+ RangeToken tok = this.parseCharacterClass(false);
+ int type;
+ while ((type = this.read()) != T_RPAREN) {
+ int ch = this.chardata;
+ if (type == T_CHAR && (ch == '-' || ch == '&')
+ || type == T_PLUS) {
+ this.next();
+ if (this.read() != T_LBRACKET) throw ex("parser.ope.1", this.offset-1);
+ RangeToken t2 = this.parseCharacterClass(false);
+ if (type == T_PLUS)
+ tok.mergeRanges(t2);
+ else if (ch == '-')
+ tok.subtractRanges(t2);
+ else if (ch == '&')
+ tok.intersectRanges(t2);
+ else
+ throw new RuntimeException("ASSERT");
+ } else {
+ throw ex("parser.ope.2", this.offset-1);
+ }
+ }
+ this.next();
+ return tok;
+ }
+
+ Token getTokenForShorthand(int ch) {
+ Token tok;
+ switch (ch) {
+ case 'd':
+ tok = this.isSet(RegularExpression.USE_UNICODE_CATEGORY)
+ ? Token.getRange("Nd", true) : Token.token_0to9;
+ break;
+ case 'D':
+ tok = this.isSet(RegularExpression.USE_UNICODE_CATEGORY)
+ ? Token.getRange("Nd", false) : Token.token_not_0to9;
+ break;
+ case 'w':
+ tok = this.isSet(RegularExpression.USE_UNICODE_CATEGORY)
+ ? Token.getRange("IsWord", true) : Token.token_wordchars;
+ break;
+ case 'W':
+ tok = this.isSet(RegularExpression.USE_UNICODE_CATEGORY)
+ ? Token.getRange("IsWord", false) : Token.token_not_wordchars;
+ break;
+ case 's':
+ tok = this.isSet(RegularExpression.USE_UNICODE_CATEGORY)
+ ? Token.getRange("IsSpace", true) : Token.token_spaces;
+ break;
+ case 'S':
+ tok = this.isSet(RegularExpression.USE_UNICODE_CATEGORY)
+ ? Token.getRange("IsSpace", false) : Token.token_not_spaces;
+ break;
+
+ default:
+ throw new RuntimeException("Internal Error: shorthands: \\u"+Integer.toString(ch, 16));
+ }
+ return tok;
+ }
+
+ /**
+ */
+ int decodeEscaped() throws ParseException {
+ if (this.read() != T_BACKSOLIDUS) throw ex("parser.next.1", this.offset-1);
+ int c = this.chardata;
+ switch (c) {
+ case 'e': c = 0x1b; break; // ESCAPE U+001B
+ case 'f': c = '\f'; break; // FORM FEED U+000C
+ case 'n': c = '\n'; break; // LINE FEED U+000A
+ case 'r': c = '\r'; break; // CRRIAGE RETURN U+000D
+ case 't': c = '\t'; break; // HORIZONTAL TABULATION U+0009
+ //case 'v': c = 0x0b; break; // VERTICAL TABULATION U+000B
+ case 'x':
+ this.next();
+ if (this.read() != T_CHAR) throw ex("parser.descape.1", this.offset-1);
+ if (this.chardata == '{') {
+ int v1 = 0;
+ int uv = 0;
+ do {
+ this.next();
+ if (this.read() != T_CHAR) throw ex("parser.descape.1", this.offset-1);
+ if ((v1 = hexChar(this.chardata)) < 0)
+ break;
+ if (uv > uv*16) throw ex("parser.descape.2", this.offset-1);
+ uv = uv*16+v1;
+ } while (true);
+ if (this.chardata != '}') throw ex("parser.descape.3", this.offset-1);
+ if (uv > Token.UTF16_MAX) throw ex("parser.descape.4", this.offset-1);
+ c = uv;
+ } else {
+ int v1 = 0;
+ if (this.read() != T_CHAR || (v1 = hexChar(this.chardata)) < 0)
+ throw ex("parser.descape.1", this.offset-1);
+ int uv = v1;
+ this.next();
+ if (this.read() != T_CHAR || (v1 = hexChar(this.chardata)) < 0)
+ throw ex("parser.descape.1", this.offset-1);
+ uv = uv*16+v1;
+ c = uv;
+ }
+ break;
+
+ case 'u':
+ int v1 = 0;
+ this.next();
+ if (this.read() != T_CHAR || (v1 = hexChar(this.chardata)) < 0)
+ throw ex("parser.descape.1", this.offset-1);
+ int uv = v1;
+ this.next();
+ if (this.read() != T_CHAR || (v1 = hexChar(this.chardata)) < 0)
+ throw ex("parser.descape.1", this.offset-1);
+ uv = uv*16+v1;
+ this.next();
+ if (this.read() != T_CHAR || (v1 = hexChar(this.chardata)) < 0)
+ throw ex("parser.descape.1", this.offset-1);
+ uv = uv*16+v1;
+ this.next();
+ if (this.read() != T_CHAR || (v1 = hexChar(this.chardata)) < 0)
+ throw ex("parser.descape.1", this.offset-1);
+ uv = uv*16+v1;
+ c = uv;
+ break;
+
+ case 'v':
+ this.next();
+ if (this.read() != T_CHAR || (v1 = hexChar(this.chardata)) < 0)
+ throw ex("parser.descape.1", this.offset-1);
+ uv = v1;
+ this.next();
+ if (this.read() != T_CHAR || (v1 = hexChar(this.chardata)) < 0)
+ throw ex("parser.descape.1", this.offset-1);
+ uv = uv*16+v1;
+ this.next();
+ if (this.read() != T_CHAR || (v1 = hexChar(this.chardata)) < 0)
+ throw ex("parser.descape.1", this.offset-1);
+ uv = uv*16+v1;
+ this.next();
+ if (this.read() != T_CHAR || (v1 = hexChar(this.chardata)) < 0)
+ throw ex("parser.descape.1", this.offset-1);
+ uv = uv*16+v1;
+ this.next();
+ if (this.read() != T_CHAR || (v1 = hexChar(this.chardata)) < 0)
+ throw ex("parser.descape.1", this.offset-1);
+ uv = uv*16+v1;
+ this.next();
+ if (this.read() != T_CHAR || (v1 = hexChar(this.chardata)) < 0)
+ throw ex("parser.descape.1", this.offset-1);
+ uv = uv*16+v1;
+ if (uv > Token.UTF16_MAX) throw ex("parser.descappe.4", this.offset-1);
+ c = uv;
+ break;
+ case 'A':
+ case 'Z':
+ case 'z':
+ throw ex("parser.descape.5", this.offset-2);
+ default:
+ }
+ return c;
+ }
+
+ static private final int hexChar(int ch) {
+ if (ch < '0') return -1;
+ if (ch > 'f') return -1;
+ if (ch <= '9') return ch-'0';
+ if (ch < 'A') return -1;
+ if (ch <= 'F') return ch-'A'+10;
+ if (ch < 'a') return -1;
+ return ch-'a'+10;
+ }
+
+ static protected final void addCaseInsensitiveChar(RangeToken tok, int c) {
+ final int[] caseMap = CaseInsensitiveMap.get(c);
+ tok.addRange(c, c);
+
+ if (caseMap != null) {
+ for (int i=0; i
+ * How to use
+ *
+ *
+ * - A. Standard way
+ *
-
+ *
+ * RegularExpression re = new RegularExpression(regex);
+ * if (re.matches(text)) { ... }
+ *
+ *
+ * - B. Capturing groups
+ *
-
+ *
+ * RegularExpression re = new RegularExpression(regex);
+ * Match match = new Match();
+ * if (re.matches(text, match)) {
+ * ... // You can refer captured texts with methods of the Match class.
+ * }
+ *
+ *
+ *
+ *
+ * Case-insensitive matching
+ *
+ * RegularExpression re = new RegularExpression(regex, "i");
+ * if (re.matches(text) >= 0) { ...}
+ *
+ *
+ * Options
+ * You can specify options to RegularExpression( regex, options)
+ * or setPattern( regex, options) .
+ * This options parameter consists of the following characters.
+ *
+ *
+ * "i"
+ * - This option indicates case-insensitive matching.
+ *
"m"
+ * - ^ and $ consider the EOL characters within the text.
+ *
"s"
+ * - . matches any one character.
+ *
"u"
+ * - Redefines \d \D \w \W \s \S \b \B \< \> as becoming to Unicode.
+ *
"w"
+ * - By this option, \b \B \< \> are processed with the method of
+ * 'Unicode Regular Expression Guidelines' Revision 4.
+ * When "w" and "u" are specified at the same time,
+ * \b \B \< \> are processed for the "w" option.
+ *
","
+ * - The parser treats a comma in a character class as a range separator.
+ * [a,b] matches a or , or b without this option.
+ * [a,b] matches a or b with this option.
+ *
+ *
"X"
+ * -
+ * By this option, the engine confoms to XML Schema: Regular Expression.
+ * The
match() method does not do subsring matching
+ * but entire string matching.
+ *
+ *
+ *
+ *
+ * Syntax
+ *
+ *
+ *
+ * Differences from the Perl 5 regular expression
+ *
+ * - There is 6-digit hexadecimal character representation (\u005cvHHHHHH.)
+ *
- Supports subtraction, union, and intersection operations for character classes.
+ *
- Not supported: \ooo (Octal character representations),
+ * \G, \C, \lc,
+ * \u005c uc, \L, \U,
+ * \E, \Q, \N{name},
+ * (?{code}), (??{code})
+ *
+ * |
+ *
+ *
+ *
+ * Meta characters are `. * + ? { [ ( ) | \ ^ $'.
+ *
+ * - Character
+ *
+ * - . (A period)
+ *
- Matches any one character except the following characters.
+ *
- LINE FEED (U+000A), CARRIAGE RETURN (U+000D),
+ * PARAGRAPH SEPARATOR (U+2029), LINE SEPARATOR (U+2028)
+ *
- This expression matches one code point in Unicode. It can match a pair of surrogates.
+ *
- When the "s" option is specified,
+ * it matches any character including the above four characters.
+ *
+ *
- \e \f \n \r \t
+ *
- Matches ESCAPE (U+001B), FORM FEED (U+000C), LINE FEED (U+000A),
+ * CARRIAGE RETURN (U+000D), HORIZONTAL TABULATION (U+0009)
+ *
+ *
- \cC
+ *
- Matches a control character.
+ * The C must be one of '@', 'A'-'Z',
+ * '[', '\u005c', ']', '^', '_'.
+ * It matches a control character of which the character code is less than
+ * the character code of the C by 0x0040.
+ *
- For example, a \cJ matches a LINE FEED (U+000A),
+ * and a \c[ matches an ESCAPE (U+001B).
+ *
+ *
- a non-meta character
+ *
- Matches the character.
+ *
+ *
- \ + a meta character
+ *
- Matches the meta character.
+ *
+ *
- \u005cxHH \u005cx{HHHH}
+ *
- Matches a character of which code point is HH (Hexadecimal) in Unicode.
+ * You can write just 2 digits for \u005cxHH, and
+ * variable length digits for \u005cx{HHHH}.
+ *
+ *
+ *
+ *
- \u005cvHHHHHH
+ *
- Matches a character of which code point is HHHHHH (Hexadecimal) in Unicode.
+ *
+ *
- \g
+ *
- Matches a grapheme.
+ *
- It is equivalent to (?[\p{ASSIGNED}]-[\p{M}\p{C}])?(?:\p{M}|[\x{094D}\x{09CD}\x{0A4D}\x{0ACD}\x{0B3D}\x{0BCD}\x{0C4D}\x{0CCD}\x{0D4D}\x{0E3A}\x{0F84}]\p{L}|[\x{1160}-\x{11A7}]|[\x{11A8}-\x{11FF}]|[\x{FF9E}\x{FF9F}])*
+ *
+ *
- \X
+ *
- Matches a combining character sequence.
+ * It is equivalent to (?:\PM\pM*)
+ *
+ *
+ *
+ * - Character class
+ *
++ * - [R1R2...Rn] (without "," option)
++ *
- [R1,R2,...,Rn] (with "," option)
+ *
- Positive character class. It matches a character in ranges.
+ *
- Rn:
+ *
+ * - A character (including \e \f \n \r \t \u005cxHH \u005cx{HHHH} \u005cvHHHHHH)
+ *
This range matches the character.
+ * - C1-C2
+ *
This range matches a character which has a code point that is >= C1's code point and <= C2's code point.
++ * - A POSIX character class: [:alpha:] [:alnum:] [:ascii:] [:cntrl:] [:digit:] [:graph:] [:lower:] [:print:] [:punct:] [:space:] [:upper:] [:xdigit:],
++ * and negative POSIX character classes in Perl like [:^alpha:]
+ *
...
+ * - \d \D \s \S \w \W \p{name} \P{name}
+ *
These expressions specifies the same ranges as the following expressions.
+ *
+ * Enumerated ranges are merged (union operation).
+ * [a-ec-z] is equivalent to [a-z]
+ *
+ * - [^R1R2...Rn] (without a "," option)
+ *
- [^R1,R2,...,Rn] (with a "," option)
+ *
- Negative character class. It matches a character not in ranges.
+ *
+ *
- (?[ranges]op[ranges]op[ranges] ... )
+ * (op is - or + or &.)
+ *
- Subtraction or union or intersection for character classes.
+ *
- For exmaple, (?[A-Z]-[CF]) is equivalent to [A-BD-EG-Z], and (?[0x00-0x7f]-[K]&[\p{Lu}]) is equivalent to [A-JL-Z].
+ *
- The result of this operations is a positive character class
+ * even if an expression includes any negative character classes.
+ * You have to take care on this in case-insensitive matching.
+ * For instance, (?[^b]) is equivalent to [\x00-ac-\x{10ffff}],
+ * which is equivalent to [^b] in case-sensitive matching.
+ * But, in case-insensitive matching, (?[^b]) matches any character because
+ * it includes 'B' and 'B' matches 'b'
+ * though [^b] is processed as [^Bb].
+ *
+ *
- [R1R2...-[RnRn+1...]] (with an "X" option)
+ * - Character class subtraction for the XML Schema.
+ * You can use this syntax when you specify an "X" option.
+ *
+ *
- \d
+ *
- Equivalent to [0-9].
+ *
- When a "u" option is set, it is equivalent to
+ * \p{Nd}.
+ *
+ *
- \D
+ *
- Equivalent to [^0-9]
+ *
- When a "u" option is set, it is equivalent to
+ * \P{Nd}.
+ *
+ *
- \s
+ *
- Equivalent to [ \f\n\r\t]
+ *
- When a "u" option is set, it is equivalent to
+ * [ \f\n\r\t\p{Z}].
+ *
+ *
- \S
+ *
- Equivalent to [^ \f\n\r\t]
+ *
- When a "u" option is set, it is equivalent to
+ * [^ \f\n\r\t\p{Z}].
+ *
+ *
- \w
+ *
- Equivalent to [a-zA-Z0-9_]
+ *
- When a "u" option is set, it is equivalent to
+ * [\p{Lu}\p{Ll}\p{Lo}\p{Nd}_].
+ *
+ *
- \W
+ *
- Equivalent to [^a-zA-Z0-9_]
+ *
- When a "u" option is set, it is equivalent to
+ * [^\p{Lu}\p{Ll}\p{Lo}\p{Nd}_].
+ *
+ *
- \p{name}
+ *
- Matches one character in the specified General Category (the second field in UnicodeData.txt) or the specified Block.
+ * The following names are available:
+ *
+ * - Unicode General Categories:
+ *
-
+ * L, M, N, Z, C, P, S, Lu, Ll, Lt, Lm, Lo, Mn, Me, Mc, Nd, Nl, No, Zs, Zl, Zp,
+ * Cc, Cf, Cn, Co, Cs, Pd, Ps, Pe, Pc, Po, Sm, Sc, Sk, So,
+ *
+ *
- (Currently the Cn category includes U+10000-U+10FFFF characters)
+ *
- Unicode Blocks:
+ *
-
+ * Basic Latin, Latin-1 Supplement, Latin Extended-A, Latin Extended-B,
+ * IPA Extensions, Spacing Modifier Letters, Combining Diacritical Marks, Greek,
+ * Cyrillic, Armenian, Hebrew, Arabic, Devanagari, Bengali, Gurmukhi, Gujarati,
+ * Oriya, Tamil, Telugu, Kannada, Malayalam, Thai, Lao, Tibetan, Georgian,
+ * Hangul Jamo, Latin Extended Additional, Greek Extended, General Punctuation,
+ * Superscripts and Subscripts, Currency Symbols, Combining Marks for Symbols,
+ * Letterlike Symbols, Number Forms, Arrows, Mathematical Operators,
+ * Miscellaneous Technical, Control Pictures, Optical Character Recognition,
+ * Enclosed Alphanumerics, Box Drawing, Block Elements, Geometric Shapes,
+ * Miscellaneous Symbols, Dingbats, CJK Symbols and Punctuation, Hiragana,
+ * Katakana, Bopomofo, Hangul Compatibility Jamo, Kanbun,
+ * Enclosed CJK Letters and Months, CJK Compatibility, CJK Unified Ideographs,
+ * Hangul Syllables, High Surrogates, High Private Use Surrogates, Low Surrogates,
+ * Private Use, CJK Compatibility Ideographs, Alphabetic Presentation Forms,
+ * Arabic Presentation Forms-A, Combining Half Marks, CJK Compatibility Forms,
+ * Small Form Variants, Arabic Presentation Forms-B, Specials,
+ * Halfwidth and Fullwidth Forms
+ *
+ *
- Others:
+ *
- ALL (Equivalent to [\u005cu0000-\u005cv10FFFF])
+ *
- ASSGINED (\p{ASSIGNED} is equivalent to \P{Cn})
+ *
- UNASSGINED
+ * (\p{UNASSIGNED} is equivalent to \p{Cn})
+ *
+ *
+ * - \P{name}
+ *
- Matches one character not in the specified General Category or the specified Block.
+ *
+ *
+ *
+ * - Selection and Quantifier
+ *
+ * - X|Y
+ *
- ...
+ *
+ *
- X*
+ *
- Matches 0 or more X.
+ *
+ *
- X+
+ *
- Matches 1 or more X.
+ *
+ *
- X?
+ *
- Matches 0 or 1 X.
+ *
+ *
- X{number}
+ *
- Matches number times.
+ *
+ *
- X{min,}
+ *
- ...
+ *
+ *
- X{min,max}
+ *
- ...
+ *
+ *
- X*?
+ *
- X+?
+ *
- X??
+ *
- X{min,}?
+ *
- X{min,max}?
+ *
- Non-greedy matching.
+ *
+ *
+ *
+ * - Grouping, Capturing, and Back-reference
+ *
+ * - (?:X)
+ *
- Grouping. "foo+" matches "foo" or "foooo".
+ * If you want it matches "foofoo" or "foofoofoo",
+ * you have to write "(?:foo)+".
+ *
+ *
- (X)
+ *
- Grouping with capturing.
+ * It make a group and applications can know
+ * where in target text a group matched with methods of a
Match instance
+ * after matches(String,Match) .
+ * The 0th group means whole of this regular expression.
+ * The Nth gorup is the inside of the Nth left parenthesis.
+ *
+ * For instance, a regular expression is
+ * " *([^<:]*) +<([^>]*)> *"
+ * and target text is
+ * "From: TAMURA Kent <kent@trl.ibm.co.jp>":
+ *
+ * Match.getCapturedText(0) :
+ * " TAMURA Kent <kent@trl.ibm.co.jp>"
+ * Match.getCapturedText(1) : "TAMURA Kent"
+ * Match.getCapturedText(2) : "kent@trl.ibm.co.jp"
+ *
+ *
+ * - \1 \2 \3 \4 \5 \6 \7 \8 \9
+ *
-
+ *
+ *
- (?>X)
+ *
- Independent expression group. ................
+ *
+ *
- (?options:X)
+ *
- (?options-options2:X)
+ *
- ............................
+ *
- The options or the options2 consists of 'i' 'm' 's' 'w'.
+ * Note that it can not contain 'u'.
+ *
+ *
- (?options)
+ *
- (?options-options2)
+ *
- ......
+ *
- These expressions must be at the beginning of a group.
+ *
+ *
+ *
+ * - Anchor
+ *
+ * - \A
+ *
- Matches the beginnig of the text.
+ *
+ *
- \Z
+ *
- Matches the end of the text, or before an EOL character at the end of the text,
+ * or CARRIAGE RETURN + LINE FEED at the end of the text.
+ *
+ *
- \z
+ *
- Matches the end of the text.
+ *
+ *
- ^
+ *
- Matches the beginning of the text. It is equivalent to \A.
+ *
- When a "m" option is set,
+ * it matches the beginning of the text, or after one of EOL characters (
+ * LINE FEED (U+000A), CARRIAGE RETURN (U+000D), LINE SEPARATOR (U+2028),
+ * PARAGRAPH SEPARATOR (U+2029).)
+ *
+ *
- $
+ *
- Matches the end of the text, or before an EOL character at the end of the text,
+ * or CARRIAGE RETURN + LINE FEED at the end of the text.
+ *
- When a "m" option is set,
+ * it matches the end of the text, or before an EOL character.
+ *
+ *
- \b
+ *
- Matches word boundary.
+ * (See a "w" option)
+ *
+ *
- \B
+ *
- Matches non word boundary.
+ * (See a "w" option)
+ *
+ *
- \<
+ *
- Matches the beginning of a word.
+ * (See a "w" option)
+ *
+ *
- \>
+ *
- Matches the end of a word.
+ * (See a "w" option)
+ *
+ *
+ * - Lookahead and lookbehind
+ *
+ * - (?=X)
+ *
- Lookahead.
+ *
+ *
- (?!X)
+ *
- Negative lookahead.
+ *
+ *
- (?<=X)
+ *
- Lookbehind.
+ *
- (Note for text capturing......)
+ *
+ *
- (?<!X)
+ *
- Negative lookbehind.
+ *
+ *
+ *
+ * - Misc.
+ *
+ * - (?(condition)yes-pattern|no-pattern),
+ *
- (?(condition)yes-pattern)
+ *
- ......
+ *
- (?#comment)
+ *
- Comment. A comment string consists of characters except ')'.
+ * You can not write comments in character classes and before quantifiers.
+ *
+ *
+ *
+ *
+ *
+ *
+ * BNF for the regular expression
+ *
+ * regex ::= ('(?' options ')')? term ('|' term)*
+ * term ::= factor+
+ * factor ::= anchors | atom (('*' | '+' | '?' | minmax ) '?'? )?
+ * | '(?#' [^)]* ')'
+ * minmax ::= '{' ([0-9]+ | [0-9]+ ',' | ',' [0-9]+ | [0-9]+ ',' [0-9]+) '}'
+ * atom ::= char | '.' | char-class | '(' regex ')' | '(?:' regex ')' | '\' [0-9]
+ * | '\w' | '\W' | '\d' | '\D' | '\s' | '\S' | category-block | '\X'
+ * | '(?>' regex ')' | '(?' options ':' regex ')'
+ * | '(?' ('(' [0-9] ')' | '(' anchors ')' | looks) term ('|' term)? ')'
+ * options ::= [imsw]* ('-' [imsw]+)?
+ * anchors ::= '^' | '$' | '\A' | '\Z' | '\z' | '\b' | '\B' | '\<' | '\>'
+ * looks ::= '(?=' regex ')' | '(?!' regex ')'
+ * | '(?<=' regex ')' | '(?<!' regex ')'
+ * char ::= '\\' | '\' [efnrtv] | '\c' [@-_] | code-point | character-1
+ * category-block ::= '\' [pP] category-symbol-1
+ * | ('\p{' | '\P{') (category-symbol | block-name
+ * | other-properties) '}'
+ * category-symbol-1 ::= 'L' | 'M' | 'N' | 'Z' | 'C' | 'P' | 'S'
+ * category-symbol ::= category-symbol-1 | 'Lu' | 'Ll' | 'Lt' | 'Lm' | Lo'
+ * | 'Mn' | 'Me' | 'Mc' | 'Nd' | 'Nl' | 'No'
+ * | 'Zs' | 'Zl' | 'Zp' | 'Cc' | 'Cf' | 'Cn' | 'Co' | 'Cs'
+ * | 'Pd' | 'Ps' | 'Pe' | 'Pc' | 'Po'
+ * | 'Sm' | 'Sc' | 'Sk' | 'So'
+ * block-name ::= (See above)
+ * other-properties ::= 'ALL' | 'ASSIGNED' | 'UNASSIGNED'
+ * character-1 ::= (any character except meta-characters)
+ *
+ * char-class ::= '[' ranges ']'
+ * | '(?[' ranges ']' ([-+&] '[' ranges ']')? ')'
+ * ranges ::= '^'? (range ','?)+
+ * range ::= '\d' | '\w' | '\s' | '\D' | '\W' | '\S' | category-block
+ * | range-char | range-char '-' range-char
+ * range-char ::= '\[' | '\]' | '\\' | '\' [,-efnrtv] | code-point | character-2
+ * code-point ::= '\x' hex-char hex-char
+ * | '\x{' hex-char+ '}'
+ * | '\v' hex-char hex-char hex-char hex-char hex-char hex-char
+ * hex-char ::= [0-9a-fA-F]
+ * character-2 ::= (any character except \[]-,)
+ *
+ *
+ *
+ * TODO
+ *
+ *
+ *
+ *
+ * @xerces.internal
+ *
+ * @author TAMURA Kent <kent@trl.ibm.co.jp>
+ * @version $Id$
+ */
+public class RegularExpression implements java.io.Serializable {
+
+ private static final long serialVersionUID = 6242499334195006401L;
+
+ static final boolean DEBUG = false;
+
+ /**
+ * Compiles a token tree into an operation flow.
+ */
+ private synchronized void compile(Token tok) {
+ if (this.operations != null)
+ return;
+ this.numberOfClosures = 0;
+ this.operations = this.compile(tok, null, false);
+ }
+
+ /**
+ * Converts a token to an operation.
+ */
+ private Op compile(Token tok, Op next, boolean reverse) {
+ Op ret;
+ switch (tok.type) {
+ case Token.DOT:
+ ret = Op.createDot();
+ ret.next = next;
+ break;
+
+ case Token.CHAR:
+ ret = Op.createChar(tok.getChar());
+ ret.next = next;
+ break;
+
+ case Token.ANCHOR:
+ ret = Op.createAnchor(tok.getChar());
+ ret.next = next;
+ break;
+
+ case Token.RANGE:
+ case Token.NRANGE:
+ ret = Op.createRange(tok);
+ ret.next = next;
+ break;
+
+ case Token.CONCAT:
+ ret = next;
+ if (!reverse) {
+ for (int i = tok.size()-1; i >= 0; i --) {
+ ret = compile(tok.getChild(i), ret, false);
+ }
+ } else {
+ for (int i = 0; i < tok.size(); i ++) {
+ ret = compile(tok.getChild(i), ret, true);
+ }
+ }
+ break;
+
+ case Token.UNION:
+ Op.UnionOp uni = Op.createUnion(tok.size());
+ for (int i = 0; i < tok.size(); i ++) {
+ uni.addElement(compile(tok.getChild(i), next, reverse));
+ }
+ ret = uni; // ret.next is null.
+ break;
+
+ case Token.CLOSURE:
+ case Token.NONGREEDYCLOSURE:
+ Token child = tok.getChild(0);
+ int min = tok.getMin();
+ int max = tok.getMax();
+ if (min >= 0 && min == max) { // {n}
+ ret = next;
+ for (int i = 0; i < min; i ++) {
+ ret = compile(child, ret, reverse);
+ }
+ break;
+ }
+ if (min > 0 && max > 0)
+ max -= min;
+ if (max > 0) {
+ // X{2,6} -> XX(X(X(XX?)?)?)?
+ ret = next;
+ for (int i = 0; i < max; i ++) {
+ Op.ChildOp q = Op.createQuestion(tok.type == Token.NONGREEDYCLOSURE);
+ q.next = next;
+ q.setChild(compile(child, ret, reverse));
+ ret = q;
+ }
+ } else {
+ Op.ChildOp op;
+ if (tok.type == Token.NONGREEDYCLOSURE) {
+ op = Op.createNonGreedyClosure();
+ } else { // Token.CLOSURE
+ op = Op.createClosure(this.numberOfClosures++);
+ }
+ op.next = next;
+ op.setChild(compile(child, op, reverse));
+ ret = op;
+ }
+ if (min > 0) {
+ for (int i = 0; i < min; i ++) {
+ ret = compile(child, ret, reverse);
+ }
+ }
+ break;
+
+ case Token.EMPTY:
+ ret = next;
+ break;
+
+ case Token.STRING:
+ ret = Op.createString(tok.getString());
+ ret.next = next;
+ break;
+
+ case Token.BACKREFERENCE:
+ ret = Op.createBackReference(tok.getReferenceNumber());
+ ret.next = next;
+ break;
+
+ case Token.PAREN:
+ if (tok.getParenNumber() == 0) {
+ ret = compile(tok.getChild(0), next, reverse);
+ } else if (reverse) {
+ next = Op.createCapture(tok.getParenNumber(), next);
+ next = compile(tok.getChild(0), next, reverse);
+ ret = Op.createCapture(-tok.getParenNumber(), next);
+ } else {
+ next = Op.createCapture(-tok.getParenNumber(), next);
+ next = compile(tok.getChild(0), next, reverse);
+ ret = Op.createCapture(tok.getParenNumber(), next);
+ }
+ break;
+
+ case Token.LOOKAHEAD:
+ ret = Op.createLook(Op.LOOKAHEAD, next, compile(tok.getChild(0), null, false));
+ break;
+ case Token.NEGATIVELOOKAHEAD:
+ ret = Op.createLook(Op.NEGATIVELOOKAHEAD, next, compile(tok.getChild(0), null, false));
+ break;
+ case Token.LOOKBEHIND:
+ ret = Op.createLook(Op.LOOKBEHIND, next, compile(tok.getChild(0), null, true));
+ break;
+ case Token.NEGATIVELOOKBEHIND:
+ ret = Op.createLook(Op.NEGATIVELOOKBEHIND, next, compile(tok.getChild(0), null, true));
+ break;
+
+ case Token.INDEPENDENT:
+ ret = Op.createIndependent(next, compile(tok.getChild(0), null, reverse));
+ break;
+
+ case Token.MODIFIERGROUP:
+ ret = Op.createModifier(next, compile(tok.getChild(0), null, reverse),
+ ((Token.ModifierToken)tok).getOptions(),
+ ((Token.ModifierToken)tok).getOptionsMask());
+ break;
+
+ case Token.CONDITION:
+ Token.ConditionToken ctok = (Token.ConditionToken)tok;
+ int ref = ctok.refNumber;
+ Op condition = ctok.condition == null ? null : compile(ctok.condition, null, reverse);
+ Op yes = compile(ctok.yes, next, reverse);
+ Op no = ctok.no == null ? null : compile(ctok.no, next, reverse);
+ ret = Op.createCondition(next, ref, condition, yes, no);
+ break;
+
+ default:
+ throw new RuntimeException("Unknown token type: "+tok.type);
+ } // switch (tok.type)
+ return ret;
+ }
+
+
+//Public
+
+ /**
+ * Checks whether the target text contains this pattern or not.
+ *
+ * @return true if the target is matched to this regular expression.
+ */
+ public boolean matches(char[] target) {
+ return this.matches(target, 0, target .length , (Match)null);
+ }
+
+ /**
+ * Checks whether the target text contains this pattern
+ * in specified range or not.
+ *
+ * @param start Start offset of the range.
+ * @param end End offset +1 of the range.
+ * @return true if the target is matched to this regular expression.
+ */
+ public boolean matches(char[] target, int start, int end) {
+ return this.matches(target, start, end, (Match)null);
+ }
+
+ /**
+ * Checks whether the target text contains this pattern or not.
+ *
+ * @param match A Match instance for storing matching result.
+ * @return Offset of the start position in target; or -1 if not match.
+ */
+ public boolean matches(char[] target, Match match) {
+ return this.matches(target, 0, target .length , match);
+ }
+
+
+ /**
+ * Checks whether the target text contains this pattern
+ * in specified range or not.
+ *
+ * @param start Start offset of the range.
+ * @param end End offset +1 of the range.
+ * @param match A Match instance for storing matching result.
+ * @return Offset of the start position in target; or -1 if not match.
+ */
+ public boolean matches(char[] target, int start, int end, Match match) {
+
+ synchronized (this) {
+ if (this.operations == null)
+ this.prepare();
+ if (this.context == null)
+ this.context = new Context();
+ }
+ Context con = null;
+ synchronized (this.context) {
+ con = this.context.inuse ? new Context() : this.context;
+ con.reset(target, start, end, this.numberOfClosures);
+ }
+ if (match != null) {
+ match.setNumberOfGroups(this.nofparen);
+ match.setSource(target);
+ } else if (this.hasBackReferences) {
+ match = new Match();
+ match.setNumberOfGroups(this.nofparen);
+ // Need not to call setSource() because
+ // a caller can not access this match instance.
+ }
+ con.match = match;
+
+ if (RegularExpression.isSet(this.options, XMLSCHEMA_MODE)) {
+ int matchEnd = this. match(con, this.operations, con.start, 1, this.options);
+ //System.err.println("DEBUG: matchEnd="+matchEnd);
+ if (matchEnd == con.limit) {
+ if (con.match != null) {
+ con.match.setBeginning(0, con.start);
+ con.match.setEnd(0, matchEnd);
+ }
+ con.setInUse(false);
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * The pattern has only fixed string.
+ * The engine uses Boyer-Moore.
+ */
+ if (this.fixedStringOnly) {
+ //System.err.println("DEBUG: fixed-only: "+this.fixedString);
+ int o = this.fixedStringTable.matches(target, con.start, con.limit);
+ if (o >= 0) {
+ if (con.match != null) {
+ con.match.setBeginning(0, o);
+ con.match.setEnd(0, o+this.fixedString.length());
+ }
+ con.setInUse(false);
+ return true;
+ }
+ con.setInUse(false);
+ return false;
+ }
+
+ /*
+ * The pattern contains a fixed string.
+ * The engine checks with Boyer-Moore whether the text contains the fixed string or not.
+ * If not, it return with false.
+ */
+ if (this.fixedString != null) {
+ int o = this.fixedStringTable.matches(target, con.start, con.limit);
+ if (o < 0) {
+ //System.err.println("Non-match in fixed-string search.");
+ con.setInUse(false);
+ return false;
+ }
+ }
+
+ int limit = con.limit-this.minlength;
+ int matchStart;
+ int matchEnd = -1;
+
+ /*
+ * Checks whether the expression starts with ".*".
+ */
+ if (this.operations != null
+ && this.operations.type == Op.CLOSURE && this.operations.getChild().type == Op.DOT) {
+ if (isSet(this.options, SINGLE_LINE)) {
+ matchStart = con.start;
+ matchEnd = this. match(con, this.operations, con.start, 1, this.options);
+ } else {
+ boolean previousIsEOL = true;
+ for (matchStart = con.start; matchStart <= limit; matchStart ++) {
+ int ch = target [ matchStart ] ;
+ if (isEOLChar(ch)) {
+ previousIsEOL = true;
+ } else {
+ if (previousIsEOL) {
+ if (0 <= (matchEnd = this. match(con, this.operations,
+ matchStart, 1, this.options)))
+ break;
+ }
+ previousIsEOL = false;
+ }
+ }
+ }
+ }
+
+ /*
+ * Optimization against the first character.
+ */
+ else if (this.firstChar != null) {
+ //System.err.println("DEBUG: with firstchar-matching: "+this.firstChar);
+ RangeToken range = this.firstChar;
+ for (matchStart = con.start; matchStart <= limit; matchStart ++) {
+ int ch = target [matchStart] ;
+ if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit) {
+ ch = REUtil.composeFromSurrogates(ch, target[matchStart+1]);
+ }
+ if (!range.match(ch)) {
+ continue;
+ }
+ if (0 <= (matchEnd = this. match(con, this.operations,
+ matchStart, 1, this.options))) {
+ break;
+ }
+ }
+ }
+
+ /*
+ * Straightforward matching.
+ */
+ else {
+ for (matchStart = con.start; matchStart <= limit; matchStart ++) {
+ if (0 <= (matchEnd = this. match(con, this.operations, matchStart, 1, this.options)))
+ break;
+ }
+ }
+
+ if (matchEnd >= 0) {
+ if (con.match != null) {
+ con.match.setBeginning(0, matchStart);
+ con.match.setEnd(0, matchEnd);
+ }
+ con.setInUse(false);
+ return true;
+ } else {
+ con.setInUse(false);
+ return false;
+ }
+ }
+
+ /**
+ * Checks whether the target text contains this pattern or not.
+ *
+ * @return true if the target is matched to this regular expression.
+ */
+ public boolean matches(String target) {
+ return this.matches(target, 0, target .length() , (Match)null);
+ }
+
+ /**
+ * Checks whether the target text contains this pattern
+ * in specified range or not.
+ *
+ * @param start Start offset of the range.
+ * @param end End offset +1 of the range.
+ * @return true if the target is matched to this regular expression.
+ */
+ public boolean matches(String target, int start, int end) {
+ return this.matches(target, start, end, (Match)null);
+ }
+
+ /**
+ * Checks whether the target text contains this pattern or not.
+ *
+ * @param match A Match instance for storing matching result.
+ * @return Offset of the start position in target; or -1 if not match.
+ */
+ public boolean matches(String target, Match match) {
+ return this.matches(target, 0, target .length() , match);
+ }
+
+ /**
+ * Checks whether the target text contains this pattern
+ * in specified range or not.
+ *
+ * @param start Start offset of the range.
+ * @param end End offset +1 of the range.
+ * @param match A Match instance for storing matching result.
+ * @return Offset of the start position in target; or -1 if not match.
+ */
+ public boolean matches(String target, int start, int end, Match match) {
+
+ synchronized (this) {
+ if (this.operations == null)
+ this.prepare();
+ if (this.context == null)
+ this.context = new Context();
+ }
+ Context con = null;
+ synchronized (this.context) {
+ con = this.context.inuse ? new Context() : this.context;
+ con.reset(target, start, end, this.numberOfClosures);
+ }
+ if (match != null) {
+ match.setNumberOfGroups(this.nofparen);
+ match.setSource(target);
+ } else if (this.hasBackReferences) {
+ match = new Match();
+ match.setNumberOfGroups(this.nofparen);
+ // Need not to call setSource() because
+ // a caller can not access this match instance.
+ }
+ con.match = match;
+
+ if (RegularExpression.isSet(this.options, XMLSCHEMA_MODE)) {
+ if (DEBUG) {
+ System.err.println("target string="+target);
+ }
+ int matchEnd = this. match(con, this.operations, con.start, 1, this.options);
+ if (DEBUG) {
+ System.err.println("matchEnd="+matchEnd);
+ System.err.println("con.limit="+con.limit);
+ }
+ if (matchEnd == con.limit) {
+ if (con.match != null) {
+ con.match.setBeginning(0, con.start);
+ con.match.setEnd(0, matchEnd);
+ }
+ con.setInUse(false);
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * The pattern has only fixed string.
+ * The engine uses Boyer-Moore.
+ */
+ if (this.fixedStringOnly) {
+ //System.err.println("DEBUG: fixed-only: "+this.fixedString);
+ int o = this.fixedStringTable.matches(target, con.start, con.limit);
+ if (o >= 0) {
+ if (con.match != null) {
+ con.match.setBeginning(0, o);
+ con.match.setEnd(0, o+this.fixedString.length());
+ }
+ con.setInUse(false);
+ return true;
+ }
+ con.setInUse(false);
+ return false;
+ }
+
+ /*
+ * The pattern contains a fixed string.
+ * The engine checks with Boyer-Moore whether the text contains the fixed string or not.
+ * If not, it return with false.
+ */
+ if (this.fixedString != null) {
+ int o = this.fixedStringTable.matches(target, con.start, con.limit);
+ if (o < 0) {
+ //System.err.println("Non-match in fixed-string search.");
+ con.setInUse(false);
+ return false;
+ }
+ }
+
+ int limit = con.limit-this.minlength;
+ int matchStart;
+ int matchEnd = -1;
+
+ /*
+ * Checks whether the expression starts with ".*".
+ */
+ if (this.operations != null
+ && this.operations.type == Op.CLOSURE && this.operations.getChild().type == Op.DOT) {
+ if (isSet(this.options, SINGLE_LINE)) {
+ matchStart = con.start;
+ matchEnd = this.match(con, this.operations, con.start, 1, this.options);
+ } else {
+ boolean previousIsEOL = true;
+ for (matchStart = con.start; matchStart <= limit; matchStart ++) {
+ int ch = target .charAt( matchStart ) ;
+ if (isEOLChar(ch)) {
+ previousIsEOL = true;
+ } else {
+ if (previousIsEOL) {
+ if (0 <= (matchEnd = this.match(con, this.operations,
+ matchStart, 1, this.options)))
+ break;
+ }
+ previousIsEOL = false;
+ }
+ }
+ }
+ }
+
+ /*
+ * Optimization against the first character.
+ */
+ else if (this.firstChar != null) {
+ //System.err.println("DEBUG: with firstchar-matching: "+this.firstChar);
+ RangeToken range = this.firstChar;
+ for (matchStart = con.start; matchStart <= limit; matchStart ++) {
+ int ch = target .charAt( matchStart ) ;
+ if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit) {
+ ch = REUtil.composeFromSurrogates(ch, target.charAt(matchStart+1));
+ }
+ if (!range.match(ch)) {
+ continue;
+ }
+ if (0 <= (matchEnd = this.match(con, this.operations,
+ matchStart, 1, this.options))) {
+ break;
+ }
+ }
+ }
+
+ /*
+ * Straightforward matching.
+ */
+ else {
+ for (matchStart = con.start; matchStart <= limit; matchStart ++) {
+ if (0 <= (matchEnd = this.match(con, this.operations, matchStart, 1, this.options)))
+ break;
+ }
+ }
+
+ if (matchEnd >= 0) {
+ if (con.match != null) {
+ con.match.setBeginning(0, matchStart);
+ con.match.setEnd(0, matchEnd);
+ }
+ con.setInUse(false);
+ return true;
+ } else {
+ con.setInUse(false);
+ return false;
+ }
+ }
+
+ /**
+ * @return -1 when not match; offset of the end of matched string when match.
+ */
+ private int match(Context con, Op op, int offset, int dx, int opts) {
+ final ExpressionTarget target = con.target;
+ final Stack opStack = new Stack();
+ final IntStack dataStack = new IntStack();
+ final boolean isSetIgnoreCase = isSet(opts, IGNORE_CASE);
+ int retValue = -1;
+ boolean returned = false;
+
+ for (;;) {
+ if (op == null || offset > con.limit || offset < con.start) {
+ if (op == null) {
+ retValue = isSet(opts, XMLSCHEMA_MODE) && offset != con.limit ? -1 : offset;
+ }
+ else {
+ retValue = -1;
+ }
+ returned = true;
+ }
+ else {
+ retValue = -1;
+ // dx value is either 1 or -1
+ switch (op.type) {
+ case Op.CHAR:
+ {
+ final int o1 = (dx > 0) ? offset : offset -1;
+ if (o1 >= con.limit || o1 < 0 || !matchChar(op.getData(), target.charAt(o1), isSetIgnoreCase)) {
+ returned = true;
+ break;
+ }
+ offset += dx;
+ op = op.next;
+ }
+ break;
+
+ case Op.DOT:
+ {
+ int o1 = (dx > 0) ? offset : offset - 1;
+ if (o1 >= con.limit || o1 < 0) {
+ returned = true;
+ break;
+ }
+ if (isSet(opts, SINGLE_LINE)) {
+ if (REUtil.isHighSurrogate(target.charAt(o1)) && o1+dx >= 0 && o1+dx < con.limit) {
+ o1 += dx;
+ }
+ }
+ else {
+ int ch = target.charAt(o1);
+ if (REUtil.isHighSurrogate(ch) && o1+dx >= 0 && o1+dx < con.limit) {
+ o1 += dx;
+ ch = REUtil.composeFromSurrogates(ch, target.charAt(o1));
+ }
+ if (isEOLChar(ch)) {
+ returned = true;
+ break;
+ }
+ }
+ offset = (dx > 0) ? o1 + 1 : o1;
+ op = op.next;
+ }
+ break;
+
+ case Op.RANGE:
+ case Op.NRANGE:
+ {
+ int o1 = (dx > 0) ? offset : offset -1;
+ if (o1 >= con.limit || o1 < 0) {
+ returned = true;
+ break;
+ }
+ int ch = target.charAt(offset);
+ if (REUtil.isHighSurrogate(ch) && o1+dx < con.limit && o1+dx >=0) {
+ o1 += dx;
+ ch = REUtil.composeFromSurrogates(ch, target.charAt(o1));
+ }
+ final RangeToken tok = op.getToken();
+ if (!tok.match(ch)) {
+ returned = true;
+ break;
+ }
+ offset = (dx > 0) ? o1+1 : o1;
+ op = op.next;
+ }
+ break;
+
+ case Op.ANCHOR:
+ {
+ if (!matchAnchor(target, op, con, offset, opts)) {
+ returned = true;
+ break;
+ }
+ op = op.next;
+ }
+ break;
+
+ case Op.BACKREFERENCE:
+ {
+ int refno = op.getData();
+ if (refno <= 0 || refno >= this.nofparen) {
+ throw new RuntimeException("Internal Error: Reference number must be more than zero: "+refno);
+ }
+ if (con.match.getBeginning(refno) < 0 || con.match.getEnd(refno) < 0) {
+ returned = true;
+ break;
+ }
+ int o2 = con.match.getBeginning(refno);
+ int literallen = con.match.getEnd(refno)-o2;
+ if (dx > 0) {
+ if (!target.regionMatches(isSetIgnoreCase, offset, con.limit, o2, literallen)) {
+ returned = true;
+ break;
+ }
+ offset += literallen;
+ }
+ else {
+ if (!target.regionMatches(isSetIgnoreCase, offset-literallen, con.limit, o2, literallen)) {
+ returned = true;
+ break;
+ }
+ offset -= literallen;
+ }
+ op = op.next;
+ }
+ break;
+
+ case Op.STRING:
+ {
+ String literal = op.getString();
+ int literallen = literal.length();
+ if (dx > 0) {
+ if (!target.regionMatches(isSetIgnoreCase, offset, con.limit, literal, literallen)) {
+ returned = true;
+ break;
+ }
+ offset += literallen;
+ }
+ else {
+ if (!target.regionMatches(isSetIgnoreCase, offset-literallen, con.limit, literal, literallen)) {
+ returned = true;
+ break;
+ }
+ offset -= literallen;
+ }
+ op = op.next;
+ }
+ break;
+
+ case Op.CLOSURE:
+ {
+ // Saves current position to avoid zero-width repeats.
+ final int id = op.getData();
+ if (con.closureContexts[id].contains(offset)) {
+ returned = true;
+ break;
+ }
+
+ con.closureContexts[id].addOffset(offset);
+ }
+ // fall through
+
+ case Op.QUESTION:
+ {
+ opStack.push(op);
+ dataStack.push(offset);
+ op = op.getChild();
+ }
+ break;
+
+ case Op.NONGREEDYCLOSURE:
+ case Op.NONGREEDYQUESTION:
+ {
+ opStack.push(op);
+ dataStack.push(offset);
+ op = op.next;
+ }
+ break;
+
+ case Op.UNION:
+ if (op.size() == 0) {
+ returned = true;
+ }
+ else {
+ opStack.push(op);
+ dataStack.push(0);
+ dataStack.push(offset);
+ op = op.elementAt(0);
+ }
+ break;
+
+ case Op.CAPTURE:
+ {
+ final int refno = op.getData();
+ if (con.match != null) {
+ if (refno > 0) {
+ dataStack.push(con.match.getBeginning(refno));
+ con.match.setBeginning(refno, offset);
+ }
+ else {
+ final int index = -refno;
+ dataStack.push(con.match.getEnd(index));
+ con.match.setEnd(index, offset);
+ }
+ opStack.push(op);
+ dataStack.push(offset);
+ }
+ op = op.next;
+ }
+ break;
+
+ case Op.LOOKAHEAD:
+ case Op.NEGATIVELOOKAHEAD:
+ case Op.LOOKBEHIND:
+ case Op.NEGATIVELOOKBEHIND:
+ {
+ opStack.push(op);
+ dataStack.push(dx);
+ dataStack.push(offset);
+ dx = (op.type == Op.LOOKAHEAD || op.type == Op.NEGATIVELOOKAHEAD) ? 1 : -1;
+ op = op.getChild();
+ }
+ break;
+
+ case Op.INDEPENDENT:
+ {
+ opStack.push(op);
+ dataStack.push(offset);
+ op = op.getChild();
+ }
+ break;
+
+ case Op.MODIFIER:
+ {
+ int localopts = opts;
+ localopts |= op.getData();
+ localopts &= ~op.getData2();
+ opStack.push(op);
+ dataStack.push(opts);
+ dataStack.push(offset);
+ opts = localopts;
+ op = op.getChild();
+ }
+ break;
+
+ case Op.CONDITION:
+ {
+ Op.ConditionOp cop = (Op.ConditionOp)op;
+ if (cop.refNumber > 0) {
+ if (cop.refNumber >= this.nofparen) {
+ throw new RuntimeException("Internal Error: Reference number must be more than zero: "+cop.refNumber);
+ }
+ if (con.match.getBeginning(cop.refNumber) >= 0
+ && con.match.getEnd(cop.refNumber) >= 0) {
+ op = cop.yes;
+ }
+ else if (cop.no != null) {
+ op = cop.no;
+ }
+ else {
+ op = cop.next;
+ }
+ }
+ else {
+ opStack.push(op);
+ dataStack.push(offset);
+ op = cop.condition;
+ }
+ }
+ break;
+
+ default:
+ throw new RuntimeException("Unknown operation type: " + op.type);
+ }
+ }
+
+ // handle recursive operations
+ while (returned) {
+ // exhausted all the operations
+ if (opStack.isEmpty()) {
+ return retValue;
+ }
+
+ op = (Op) opStack.pop();
+ offset = dataStack.pop();
+
+ switch (op.type) {
+ case Op.CLOSURE:
+ case Op.QUESTION:
+ if (retValue < 0) {
+ op = op.next;
+ returned = false;
+ }
+ break;
+
+ case Op.NONGREEDYCLOSURE:
+ case Op.NONGREEDYQUESTION:
+ if (retValue < 0) {
+ op = op.getChild();
+ returned = false;
+ }
+ break;
+
+ case Op.UNION:
+ {
+ int unionIndex = dataStack.pop();
+ if (DEBUG) {
+ System.err.println("UNION: "+unionIndex+", ret="+retValue);
+ }
+
+ if (retValue < 0) {
+ if (++unionIndex < op.size()) {
+ opStack.push(op);
+ dataStack.push(unionIndex);
+ dataStack.push(offset);
+ op = op.elementAt(unionIndex);
+ returned = false;
+ }
+ else {
+ retValue = -1;
+ }
+ }
+ }
+ break;
+
+ case Op.CAPTURE:
+ final int refno = op.getData();
+ final int saved = dataStack.pop();
+ if (retValue < 0) {
+ if (refno > 0) {
+ con.match.setBeginning(refno, saved);
+ }
+ else {
+ con.match.setEnd(-refno, saved);
+ }
+ }
+ break;
+
+ case Op.LOOKAHEAD:
+ case Op.LOOKBEHIND:
+ {
+ dx = dataStack.pop();
+ if (0 <= retValue) {
+ op = op.next;
+ returned = false;
+ }
+ retValue = -1;
+ }
+ break;
+
+ case Op.NEGATIVELOOKAHEAD:
+ case Op.NEGATIVELOOKBEHIND:
+ {
+ dx = dataStack.pop();
+ if (0 > retValue) {
+ op = op.next;
+ returned = false;
+ }
+ retValue = -1;
+ }
+ break;
+
+ case Op.MODIFIER:
+ opts = dataStack.pop();
+ // fall through
+
+ case Op.INDEPENDENT:
+ if (retValue >= 0) {
+ offset = retValue;
+ op = op.next;
+ returned = false;
+ }
+ break;
+
+ case Op.CONDITION:
+ {
+ final Op.ConditionOp cop = (Op.ConditionOp)op;
+ if (0 <= retValue) {
+ op = cop.yes;
+ }
+ else if (cop.no != null) {
+ op = cop.no;
+ }
+ else {
+ op = cop.next;
+ }
+ }
+ returned = false;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ private boolean matchChar(int ch, int other, boolean ignoreCase) {
+ return (ignoreCase) ? matchIgnoreCase(ch, other) : ch == other;
+ }
+
+ boolean matchAnchor(ExpressionTarget target, Op op, Context con, int offset, int opts) {
+ boolean go = false;
+ switch (op.getData()) {
+ case '^':
+ if (isSet(opts, MULTIPLE_LINES)) {
+ if (!(offset == con.start
+ || offset > con.start && offset < con.limit && isEOLChar(target.charAt(offset-1))))
+ return false;
+ } else {
+ if (offset != con.start)
+ return false;
+ }
+ break;
+
+ case '@': // Internal use only.
+ // The @ always matches line beginnings.
+ if (!(offset == con.start
+ || offset > con.start && isEOLChar(target.charAt(offset-1))))
+ return false;
+ break;
+
+ case '$':
+ if (isSet(opts, MULTIPLE_LINES)) {
+ if (!(offset == con.limit
+ || offset < con.limit && isEOLChar(target.charAt(offset))))
+ return false;
+ } else {
+ if (!(offset == con.limit
+ || offset+1 == con.limit && isEOLChar(target.charAt(offset))
+ || offset+2 == con.limit && target.charAt(offset) == CARRIAGE_RETURN
+ && target.charAt(offset+1) == LINE_FEED))
+ return false;
+ }
+ break;
+
+ case 'A':
+ if (offset != con.start) return false;
+ break;
+
+ case 'Z':
+ if (!(offset == con.limit
+ || offset+1 == con.limit && isEOLChar(target.charAt(offset))
+ || offset+2 == con.limit && target.charAt(offset) == CARRIAGE_RETURN
+ && target.charAt(offset+1) == LINE_FEED))
+ return false;
+ break;
+
+ case 'z':
+ if (offset != con.limit) return false;
+ break;
+
+ case 'b':
+ if (con.length == 0)
+ return false;
+ {
+ int after = getWordType(target, con.start, con.limit, offset, opts);
+ if (after == WT_IGNORE) return false;
+ int before = getPreviousWordType(target, con.start, con.limit, offset, opts);
+ if (after == before) return false;
+ }
+ break;
+
+ case 'B':
+ if (con.length == 0)
+ go = true;
+ else {
+ int after = getWordType(target, con.start, con.limit, offset, opts);
+ go = after == WT_IGNORE
+ || after == getPreviousWordType(target, con.start, con.limit, offset, opts);
+ }
+ if (!go) return false;
+ break;
+
+ case '<':
+ if (con.length == 0 || offset == con.limit) return false;
+ if (getWordType(target, con.start, con.limit, offset, opts) != WT_LETTER
+ || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_OTHER)
+ return false;
+ break;
+
+ case '>':
+ if (con.length == 0 || offset == con.start) return false;
+ if (getWordType(target, con.start, con.limit, offset, opts) != WT_OTHER
+ || getPreviousWordType(target, con.start, con.limit, offset, opts) != WT_LETTER)
+ return false;
+ break;
+ } // switch anchor type
+
+ return true;
+ }
+
+ private static final int getPreviousWordType(ExpressionTarget target, int begin, int end,
+ int offset, int opts) {
+ int ret = getWordType(target, begin, end, --offset, opts);
+ while (ret == WT_IGNORE)
+ ret = getWordType(target, begin, end, --offset, opts);
+ return ret;
+ }
+
+ private static final int getWordType(ExpressionTarget target, int begin, int end,
+ int offset, int opts) {
+ if (offset < begin || offset >= end) return WT_OTHER;
+ return getWordType0(target.charAt(offset) , opts);
+ }
+
+
+ /**
+ * Checks whether the target text contains this pattern or not.
+ *
+ * @return true if the target is matched to this regular expression.
+ */
+ public boolean matches(CharacterIterator target) {
+ return this.matches(target, (Match)null);
+ }
+
+
+ /**
+ * Checks whether the target text contains this pattern or not.
+ *
+ * @param match A Match instance for storing matching result.
+ * @return Offset of the start position in target; or -1 if not match.
+ */
+ public boolean matches(CharacterIterator target, Match match) {
+ int start = target.getBeginIndex();
+ int end = target.getEndIndex();
+
+
+
+ synchronized (this) {
+ if (this.operations == null)
+ this.prepare();
+ if (this.context == null)
+ this.context = new Context();
+ }
+ Context con = null;
+ synchronized (this.context) {
+ con = this.context.inuse ? new Context() : this.context;
+ con.reset(target, start, end, this.numberOfClosures);
+ }
+ if (match != null) {
+ match.setNumberOfGroups(this.nofparen);
+ match.setSource(target);
+ } else if (this.hasBackReferences) {
+ match = new Match();
+ match.setNumberOfGroups(this.nofparen);
+ // Need not to call setSource() because
+ // a caller can not access this match instance.
+ }
+ con.match = match;
+
+ if (RegularExpression.isSet(this.options, XMLSCHEMA_MODE)) {
+ int matchEnd = this.match(con, this.operations, con.start, 1, this.options);
+ //System.err.println("DEBUG: matchEnd="+matchEnd);
+ if (matchEnd == con.limit) {
+ if (con.match != null) {
+ con.match.setBeginning(0, con.start);
+ con.match.setEnd(0, matchEnd);
+ }
+ con.setInUse(false);
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * The pattern has only fixed string.
+ * The engine uses Boyer-Moore.
+ */
+ if (this.fixedStringOnly) {
+ //System.err.println("DEBUG: fixed-only: "+this.fixedString);
+ int o = this.fixedStringTable.matches(target, con.start, con.limit);
+ if (o >= 0) {
+ if (con.match != null) {
+ con.match.setBeginning(0, o);
+ con.match.setEnd(0, o+this.fixedString.length());
+ }
+ con.setInUse(false);
+ return true;
+ }
+ con.setInUse(false);
+ return false;
+ }
+
+ /*
+ * The pattern contains a fixed string.
+ * The engine checks with Boyer-Moore whether the text contains the fixed string or not.
+ * If not, it return with false.
+ */
+ if (this.fixedString != null) {
+ int o = this.fixedStringTable.matches(target, con.start, con.limit);
+ if (o < 0) {
+ //System.err.println("Non-match in fixed-string search.");
+ con.setInUse(false);
+ return false;
+ }
+ }
+
+ int limit = con.limit-this.minlength;
+ int matchStart;
+ int matchEnd = -1;
+
+ /*
+ * Checks whether the expression starts with ".*".
+ */
+ if (this.operations != null
+ && this.operations.type == Op.CLOSURE && this.operations.getChild().type == Op.DOT) {
+ if (isSet(this.options, SINGLE_LINE)) {
+ matchStart = con.start;
+ matchEnd = this.match(con, this.operations, con.start, 1, this.options);
+ } else {
+ boolean previousIsEOL = true;
+ for (matchStart = con.start; matchStart <= limit; matchStart ++) {
+ int ch = target .setIndex( matchStart ) ;
+ if (isEOLChar(ch)) {
+ previousIsEOL = true;
+ } else {
+ if (previousIsEOL) {
+ if (0 <= (matchEnd = this.match(con, this.operations,
+ matchStart, 1, this.options)))
+ break;
+ }
+ previousIsEOL = false;
+ }
+ }
+ }
+ }
+
+ /*
+ * Optimization against the first character.
+ */
+ else if (this.firstChar != null) {
+ //System.err.println("DEBUG: with firstchar-matching: "+this.firstChar);
+ RangeToken range = this.firstChar;
+ for (matchStart = con.start; matchStart <= limit; matchStart ++) {
+ int ch = target .setIndex( matchStart ) ;
+ if (REUtil.isHighSurrogate(ch) && matchStart+1 < con.limit) {
+ ch = REUtil.composeFromSurrogates(ch, target.setIndex(matchStart+1));
+ }
+ if (!range.match(ch)) {
+ continue;
+ }
+ if (0 <= (matchEnd = this.match(con, this.operations,
+ matchStart, 1, this.options))) {
+ break;
+ }
+ }
+ }
+
+ /*
+ * Straightforward matching.
+ */
+ else {
+ for (matchStart = con.start; matchStart <= limit; matchStart ++) {
+ if (0 <= (matchEnd = this. match(con, this.operations, matchStart, 1, this.options)))
+ break;
+ }
+ }
+
+ if (matchEnd >= 0) {
+ if (con.match != null) {
+ con.match.setBeginning(0, matchStart);
+ con.match.setEnd(0, matchEnd);
+ }
+ con.setInUse(false);
+ return true;
+ } else {
+ con.setInUse(false);
+ return false;
+ }
+ }
+
+ // ================================================================
+
+ /**
+ * A regular expression.
+ * @serial
+ */
+ String regex;
+ /**
+ * @serial
+ */
+ int options;
+
+ /**
+ * The number of parenthesis in the regular expression.
+ * @serial
+ */
+ int nofparen;
+ /**
+ * Internal representation of the regular expression.
+ * @serial
+ */
+ Token tokentree;
+
+ boolean hasBackReferences = false;
+
+ transient int minlength;
+ transient Op operations = null;
+ transient int numberOfClosures;
+ transient Context context = null;
+ transient RangeToken firstChar = null;
+
+ transient String fixedString = null;
+ transient int fixedStringOptions;
+ transient BMPattern fixedStringTable = null;
+ transient boolean fixedStringOnly = false;
+
+ static abstract class ExpressionTarget {
+ abstract char charAt(int index);
+ abstract boolean regionMatches(boolean ignoreCase, int offset, int limit, String part, int partlen);
+ abstract boolean regionMatches(boolean ignoreCase, int offset, int limit, int offset2, int partlen);
+ }
+
+ static final class StringTarget extends ExpressionTarget {
+
+ private String target;
+
+ StringTarget(String target) {
+ this.target = target;
+ }
+
+ final void resetTarget(String target) {
+ this.target = target;
+ }
+
+ final char charAt(int index) {
+ return target.charAt(index);
+ }
+
+ final boolean regionMatches(boolean ignoreCase, int offset, int limit,
+ String part, int partlen) {
+ if (limit-offset < partlen) {
+ return false;
+ }
+ return (ignoreCase) ? target.regionMatches(true, offset, part, 0, partlen) : target.regionMatches(offset, part, 0, partlen);
+ }
+
+ final boolean regionMatches(boolean ignoreCase, int offset, int limit,
+ int offset2, int partlen) {
+ if (limit-offset < partlen) {
+ return false;
+ }
+ return (ignoreCase) ? target.regionMatches(true, offset, target, offset2, partlen)
+ : target.regionMatches(offset, target, offset2, partlen);
+ }
+ }
+
+ static final class CharArrayTarget extends ExpressionTarget {
+
+ char[] target;
+
+ CharArrayTarget(char[] target) {
+ this.target = target;
+ }
+
+ final void resetTarget(char[] target) {
+ this.target = target;
+ }
+
+ char charAt(int index) {
+ return target[index];
+ }
+
+ final boolean regionMatches(boolean ignoreCase, int offset, int limit,
+ String part, int partlen) {
+ if (offset < 0 || limit-offset < partlen) {
+ return false;
+ }
+ return (ignoreCase) ? regionMatchesIgnoreCase(offset, limit, part, partlen)
+ : regionMatches(offset, limit, part, partlen);
+ }
+
+ private final boolean regionMatches(int offset, int limit, String part, int partlen) {
+ int i = 0;
+ while (partlen-- > 0) {
+ if (target[offset++] != part.charAt(i++)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private final boolean regionMatchesIgnoreCase(int offset, int limit, String part, int partlen) {
+ int i = 0;
+ while (partlen-- > 0) {
+ final char ch1 = target[offset++] ;
+ final char ch2 = part.charAt(i++);
+ if (ch1 == ch2) {
+ continue;
+ }
+ final char uch1 = Character.toUpperCase(ch1);
+ final char uch2 = Character.toUpperCase(ch2);
+ if (uch1 == uch2) {
+ continue;
+ }
+ if (Character.toLowerCase(uch1) != Character.toLowerCase(uch2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ final boolean regionMatches(boolean ignoreCase, int offset, int limit, int offset2, int partlen) {
+ if (offset < 0 || limit-offset < partlen) {
+ return false;
+ }
+ return (ignoreCase) ? regionMatchesIgnoreCase(offset, limit, offset2, partlen)
+ : regionMatches(offset, limit, offset2, partlen);
+ }
+
+ private final boolean regionMatches(int offset, int limit, int offset2, int partlen) {
+ int i = offset2;
+ while (partlen-- > 0) {
+ if ( target [ offset++ ] != target [ i++ ] )
+ return false;
+ }
+ return true;
+ }
+
+ private final boolean regionMatchesIgnoreCase(int offset, int limit, int offset2, int partlen) {
+ int i = offset2;
+ while (partlen-- > 0) {
+ final char ch1 = target[offset++] ;
+ final char ch2 = target[i++] ;
+ if (ch1 == ch2) {
+ continue;
+ }
+ final char uch1 = Character.toUpperCase(ch1);
+ final char uch2 = Character.toUpperCase(ch2);
+ if (uch1 == uch2) {
+ continue;
+ }
+ if (Character.toLowerCase(uch1) != Character.toLowerCase(uch2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ static final class CharacterIteratorTarget extends ExpressionTarget {
+ CharacterIterator target;
+
+ CharacterIteratorTarget(CharacterIterator target) {
+ this.target = target;
+ }
+
+ final void resetTarget(CharacterIterator target) {
+ this.target = target;
+ }
+
+ final char charAt(int index) {
+ return target.setIndex(index);
+ }
+
+ final boolean regionMatches(boolean ignoreCase, int offset, int limit,
+ String part, int partlen) {
+ if (offset < 0 || limit-offset < partlen) {
+ return false;
+ }
+ return (ignoreCase) ? regionMatchesIgnoreCase(offset, limit, part, partlen)
+ : regionMatches(offset, limit, part, partlen);
+ }
+
+ private final boolean regionMatches(int offset, int limit, String part, int partlen) {
+ int i = 0;
+ while (partlen-- > 0) {
+ if (target.setIndex(offset++) != part.charAt(i++)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private final boolean regionMatchesIgnoreCase(int offset, int limit, String part, int partlen) {
+ int i = 0;
+ while (partlen-- > 0) {
+ final char ch1 = target.setIndex(offset++) ;
+ final char ch2 = part.charAt(i++);
+ if (ch1 == ch2) {
+ continue;
+ }
+ final char uch1 = Character.toUpperCase(ch1);
+ final char uch2 = Character.toUpperCase(ch2);
+ if (uch1 == uch2) {
+ continue;
+ }
+ if (Character.toLowerCase(uch1) != Character.toLowerCase(uch2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ final boolean regionMatches(boolean ignoreCase, int offset, int limit, int offset2, int partlen) {
+ if (offset < 0 || limit-offset < partlen) {
+ return false;
+ }
+ return (ignoreCase) ? regionMatchesIgnoreCase(offset, limit, offset2, partlen)
+ : regionMatches(offset, limit, offset2, partlen);
+ }
+
+ private final boolean regionMatches(int offset, int limit, int offset2, int partlen) {
+ int i = offset2;
+ while (partlen-- > 0) {
+ if (target.setIndex(offset++) != target.setIndex(i++)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private final boolean regionMatchesIgnoreCase(int offset, int limit, int offset2, int partlen) {
+ int i = offset2;
+ while (partlen-- > 0) {
+ final char ch1 = target.setIndex(offset++) ;
+ final char ch2 = target.setIndex(i++) ;
+ if (ch1 == ch2) {
+ continue;
+ }
+ final char uch1 = Character.toUpperCase(ch1);
+ final char uch2 = Character.toUpperCase(ch2);
+ if (uch1 == uch2) {
+ continue;
+ }
+ if (Character.toLowerCase(uch1) != Character.toLowerCase(uch2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ static final class ClosureContext {
+
+ int[] offsets = new int[4];
+ int currentIndex = 0;
+
+ boolean contains(int offset) {
+ for (int i=0; i= 0x10000) { // Op.CHAR
+ this.fixedString = REUtil.decomposeToSurrogates(this.operations.getData());
+ } else {
+ char[] ac = new char[1];
+ ac[0] = (char)this.operations.getData();
+ this.fixedString = new String(ac);
+ }
+ this.fixedStringOptions = this.options;
+ this.fixedStringTable = new BMPattern(this.fixedString, 256,
+ isSet(this.fixedStringOptions, IGNORE_CASE));
+ } else if (!isSet(this.options, PROHIBIT_FIXED_STRING_OPTIMIZATION)
+ && !isSet(this.options, XMLSCHEMA_MODE)) {
+ Token.FixedStringContainer container = new Token.FixedStringContainer();
+ this.tokentree.findFixedString(container, this.options);
+ this.fixedString = container.token == null ? null : container.token.getString();
+ this.fixedStringOptions = container.options;
+ if (this.fixedString != null && this.fixedString.length() < 2)
+ this.fixedString = null;
+ // This pattern has a fixed string of which length is more than one.
+ if (this.fixedString != null) {
+ this.fixedStringTable = new BMPattern(this.fixedString, 256,
+ isSet(this.fixedStringOptions, IGNORE_CASE));
+ if (DEBUG) {
+ System.err.println("DEBUG: The longest fixed string: "+this.fixedString.length()
+ +"/" //+this.fixedString
+ +"/"+REUtil.createOptionString(this.fixedStringOptions));
+ System.err.print("String: ");
+ REUtil.dumpString(this.fixedString);
+ }
+ }
+ }
+ }
+
+ /**
+ * An option.
+ * If you specify this option, (X)
+ * captures matched text, and (:?X)
+ * does not capture.
+ *
+ * @see #RegularExpression(java.lang.String,int)
+ * @see #setPattern(java.lang.String,int)
+ static final int MARK_PARENS = 1<<0;
+ */
+
+ /**
+ * "i"
+ */
+ static final int IGNORE_CASE = 1<<1;
+
+ /**
+ * "s"
+ */
+ static final int SINGLE_LINE = 1<<2;
+
+ /**
+ * "m"
+ */
+ static final int MULTIPLE_LINES = 1<<3;
+
+ /**
+ * "x"
+ */
+ static final int EXTENDED_COMMENT = 1<<4;
+
+ /**
+ * This option redefines \d \D \w \W \s \S.
+ *
+ * @see #RegularExpression(java.lang.String,int)
+ * @see #setPattern(java.lang.String,int)
+ * @see #UNICODE_WORD_BOUNDARY
+ */
+ static final int USE_UNICODE_CATEGORY = 1<<5; // "u"
+
+ /**
+ * An option.
+ * This enables to process locale-independent word boundary for \b \B \< \>.
+ * By default, the engine considers a position between a word character
+ * (\w) and a non word character
+ * is a word boundary.
+ * By this option, the engine checks word boundaries with the method of
+ * 'Unicode Regular Expression Guidelines' Revision 4.
+ *
+ * @see #RegularExpression(java.lang.String,int)
+ * @see #setPattern(java.lang.String,int)
+ */
+ static final int UNICODE_WORD_BOUNDARY = 1<<6; // "w"
+
+ /**
+ * "H"
+ */
+ static final int PROHIBIT_HEAD_CHARACTER_OPTIMIZATION = 1<<7;
+ /**
+ * "F"
+ */
+ static final int PROHIBIT_FIXED_STRING_OPTIMIZATION = 1<<8;
+ /**
+ * "X". XML Schema mode.
+ */
+ static final int XMLSCHEMA_MODE = 1<<9;
+ /**
+ * ",".
+ */
+ static final int SPECIAL_COMMA = 1<<10;
+
+
+ private static final boolean isSet(int options, int flag) {
+ return (options & flag) == flag;
+ }
+
+ /**
+ * Creates a new RegularExpression instance.
+ *
+ * @param regex A regular expression
+ * @exception org.apache.xerces.utils.regex.ParseException regex is not conforming to the syntax.
+ */
+ public RegularExpression(String regex) throws ParseException {
+ this(regex, null);
+ }
+
+ /**
+ * Creates a new RegularExpression instance with options.
+ *
+ * @param regex A regular expression
+ * @param options A String consisted of "i" "m" "s" "u" "w" "," "X"
+ * @exception org.apache.xerces.utils.regex.ParseException regex is not conforming to the syntax.
+ */
+ public RegularExpression(String regex, String options) throws ParseException {
+ this.setPattern(regex, options);
+ }
+
+ /**
+ * Creates a new RegularExpression instance with options.
+ *
+ * @param regex A regular expression
+ * @param options A String consisted of "i" "m" "s" "u" "w" "," "X"
+ * @exception org.apache.xerces.utils.regex.ParseException regex is not conforming to the syntax.
+ */
+ public RegularExpression(String regex, String options, Locale locale) throws ParseException {
+ this.setPattern(regex, options, locale);
+ }
+
+ RegularExpression(String regex, Token tok, int parens, boolean hasBackReferences, int options) {
+ this.regex = regex;
+ this.tokentree = tok;
+ this.nofparen = parens;
+ this.options = options;
+ this.hasBackReferences = hasBackReferences;
+ }
+
+ /**
+ *
+ */
+ public void setPattern(String newPattern) throws ParseException {
+ this.setPattern(newPattern, Locale.getDefault());
+ }
+
+ public void setPattern(String newPattern, Locale locale) throws ParseException {
+ this.setPattern(newPattern, this.options, locale);
+ }
+
+ private void setPattern(String newPattern, int options, Locale locale) throws ParseException {
+ this.regex = newPattern;
+ this.options = options;
+ RegexParser rp = RegularExpression.isSet(this.options, RegularExpression.XMLSCHEMA_MODE)
+ ? new ParserForXMLSchema(locale) : new RegexParser(locale);
+ this.tokentree = rp.parse(this.regex, this.options);
+ this.nofparen = rp.parennumber;
+ this.hasBackReferences = rp.hasBackReferences;
+
+ this.operations = null;
+ this.context = null;
+ }
+ /**
+ *
+ */
+ public void setPattern(String newPattern, String options) throws ParseException {
+ this.setPattern(newPattern, options, Locale.getDefault());
+ }
+
+ public void setPattern(String newPattern, String options, Locale locale) throws ParseException {
+ this.setPattern(newPattern, REUtil.parseOptions(options), locale);
+ }
+
+ /**
+ *
+ */
+ public String getPattern() {
+ return this.regex;
+ }
+
+ /**
+ * Represents this instence in String.
+ */
+ public String toString() {
+ return this.tokentree.toString(this.options);
+ }
+
+ /**
+ * Returns a option string.
+ * The order of letters in it may be different from a string specified
+ * in a constructor or setPattern() .
+ *
+ * @see #RegularExpression(java.lang.String,java.lang.String)
+ * @see #setPattern(java.lang.String,java.lang.String)
+ */
+ public String getOptions() {
+ return REUtil.createOptionString(this.options);
+ }
+
+ /**
+ * Return true if patterns are the same and the options are equivalent.
+ */
+ public boolean equals(Object obj) {
+ if (obj == null) return false;
+ if (!(obj instanceof RegularExpression))
+ return false;
+ RegularExpression r = (RegularExpression)obj;
+ return this.regex.equals(r.regex) && this.options == r.options;
+ }
+
+ boolean equals(String pattern, int options) {
+ return this.regex.equals(pattern) && this.options == options;
+ }
+
+ /**
+ *
+ */
+ public int hashCode() {
+ return (this.regex+"/"+this.getOptions()).hashCode();
+ }
+
+ /**
+ * Return the number of regular expression groups.
+ * This method returns 1 when the regular expression has no capturing-parenthesis.
+ *
+ */
+ public int getNumberOfGroups() {
+ return this.nofparen;
+ }
+
+ // ================================================================
+
+ private static final int WT_IGNORE = 0;
+ private static final int WT_LETTER = 1;
+ private static final int WT_OTHER = 2;
+ private static final int getWordType0(char ch, int opts) {
+ if (!isSet(opts, UNICODE_WORD_BOUNDARY)) {
+ if (isSet(opts, USE_UNICODE_CATEGORY)) {
+ return (Token.getRange("IsWord", true).match(ch)) ? WT_LETTER : WT_OTHER;
+ }
+ return isWordChar(ch) ? WT_LETTER : WT_OTHER;
+ }
+
+ switch (Character.getType(ch)) {
+ case Character.UPPERCASE_LETTER: // L
+ case Character.LOWERCASE_LETTER: // L
+ case Character.TITLECASE_LETTER: // L
+ case Character.MODIFIER_LETTER: // L
+ case Character.OTHER_LETTER: // L
+ case Character.LETTER_NUMBER: // N
+ case Character.DECIMAL_DIGIT_NUMBER: // N
+ case Character.OTHER_NUMBER: // N
+ case Character.COMBINING_SPACING_MARK: // Mc
+ return WT_LETTER;
+
+ case Character.FORMAT: // Cf
+ case Character.NON_SPACING_MARK: // Mn
+ case Character.ENCLOSING_MARK: // Mc
+ return WT_IGNORE;
+
+ case Character.CONTROL: // Cc
+ switch (ch) {
+ case '\t':
+ case '\n':
+ case '\u000B':
+ case '\f':
+ case '\r':
+ return WT_OTHER;
+ default:
+ return WT_IGNORE;
+ }
+
+ default:
+ return WT_OTHER;
+ }
+ }
+
+ // ================================================================
+
+ static final int LINE_FEED = 0x000A;
+ static final int CARRIAGE_RETURN = 0x000D;
+ static final int LINE_SEPARATOR = 0x2028;
+ static final int PARAGRAPH_SEPARATOR = 0x2029;
+
+ private static final boolean isEOLChar(int ch) {
+ return ch == LINE_FEED || ch == CARRIAGE_RETURN || ch == LINE_SEPARATOR
+ || ch == PARAGRAPH_SEPARATOR;
+ }
+
+ private static final boolean isWordChar(int ch) { // Legacy word characters
+ if (ch == '_') return true;
+ if (ch < '0') return false;
+ if (ch > 'z') return false;
+ if (ch <= '9') return true;
+ if (ch < 'A') return false;
+ if (ch <= 'Z') return true;
+ if (ch < 'a') return false;
+ return true;
+ }
+
+ private static final boolean matchIgnoreCase(int chardata, int ch) {
+ if (chardata == ch) return true;
+ if (chardata > 0xffff || ch > 0xffff) return false;
+ char uch1 = Character.toUpperCase((char)chardata);
+ char uch2 = Character.toUpperCase((char)ch);
+ if (uch1 == uch2) return true;
+ return Character.toLowerCase(uch1) == Character.toLowerCase(uch2);
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/Token.java b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/Token.java
new file mode 100644
index 0000000..df1b1fe
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/Token.java
@@ -0,0 +1,1531 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xpath.regex;
+
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * This class represents a node in parse tree.
+ *
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+class Token implements java.io.Serializable {
+
+ private static final long serialVersionUID = 8484976002585487481L;
+
+ static final boolean COUNTTOKENS = true;
+ static int tokens = 0;
+
+ static final int CHAR = 0; // Literal char
+ static final int DOT = 11; // .
+ static final int CONCAT = 1; // XY
+ static final int UNION = 2; // X|Y|Z
+ static final int CLOSURE = 3; // X*
+ static final int RANGE = 4; // [a-zA-Z] etc.
+ static final int NRANGE = 5; // [^a-zA-Z] etc.
+ static final int PAREN = 6; // (X) or (?:X)
+ static final int EMPTY = 7; //
+ static final int ANCHOR = 8; // ^ $ \b \B \< \> \A \Z \z
+ static final int NONGREEDYCLOSURE = 9; // *? +?
+ static final int STRING = 10; // strings
+ static final int BACKREFERENCE = 12; // back references
+ static final int LOOKAHEAD = 20; // (?=...)
+ static final int NEGATIVELOOKAHEAD = 21; // (?!...)
+ static final int LOOKBEHIND = 22; // (?<=...)
+ static final int NEGATIVELOOKBEHIND = 23; // (?...)
+ static final int MODIFIERGROUP = 25; // (?ims-ims:...)
+ static final int CONDITION = 26; // (?(...)yes|no)
+
+ static final int UTF16_MAX = 0x10ffff;
+
+ final int type;
+
+ static Token token_dot;
+ static Token token_0to9;
+ static Token token_wordchars;
+ static Token token_not_0to9;
+ static Token token_not_wordchars;
+ static Token token_spaces;
+ static Token token_not_spaces;
+ static Token token_empty;
+ static Token token_linebeginning;
+ static Token token_linebeginning2;
+ static Token token_lineend;
+ static Token token_stringbeginning;
+ static Token token_stringend;
+ static Token token_stringend2;
+ static Token token_wordedge;
+ static Token token_not_wordedge;
+ static Token token_wordbeginning;
+ static Token token_wordend;
+ static {
+ Token.token_empty = new Token(Token.EMPTY);
+
+ Token.token_linebeginning = Token.createAnchor('^');
+ Token.token_linebeginning2 = Token.createAnchor('@');
+ Token.token_lineend = Token.createAnchor('$');
+ Token.token_stringbeginning = Token.createAnchor('A');
+ Token.token_stringend = Token.createAnchor('z');
+ Token.token_stringend2 = Token.createAnchor('Z');
+ Token.token_wordedge = Token.createAnchor('b');
+ Token.token_not_wordedge = Token.createAnchor('B');
+ Token.token_wordbeginning = Token.createAnchor('<');
+ Token.token_wordend = Token.createAnchor('>');
+
+ Token.token_dot = new Token(Token.DOT);
+
+ Token.token_0to9 = Token.createRange();
+ Token.token_0to9.addRange('0', '9');
+ Token.token_wordchars = Token.createRange();
+ Token.token_wordchars.addRange('0', '9');
+ Token.token_wordchars.addRange('A', 'Z');
+ Token.token_wordchars.addRange('_', '_');
+ Token.token_wordchars.addRange('a', 'z');
+ Token.token_spaces = Token.createRange();
+ Token.token_spaces.addRange('\t', '\t');
+ Token.token_spaces.addRange('\n', '\n');
+ Token.token_spaces.addRange('\f', '\f');
+ Token.token_spaces.addRange('\r', '\r');
+ Token.token_spaces.addRange(' ', ' ');
+
+ Token.token_not_0to9 = Token.complementRanges(Token.token_0to9);
+ Token.token_not_wordchars = Token.complementRanges(Token.token_wordchars);
+ Token.token_not_spaces = Token.complementRanges(Token.token_spaces);
+ }
+
+ static Token.ParenToken createLook(int type, Token child) {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.ParenToken(type, child, 0);
+ }
+ static Token.ParenToken createParen(Token child, int pnumber) {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.ParenToken(Token.PAREN, child, pnumber);
+ }
+ static Token.ClosureToken createClosure(Token tok) {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.ClosureToken(Token.CLOSURE, tok);
+ }
+ static Token.ClosureToken createNGClosure(Token tok) {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.ClosureToken(Token.NONGREEDYCLOSURE, tok);
+ }
+ static Token.ConcatToken createConcat(Token tok1, Token tok2) {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.ConcatToken(tok1, tok2);
+ }
+ static Token.UnionToken createConcat() {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.UnionToken(Token.CONCAT); // *** It is not a bug.
+ }
+ static Token.UnionToken createUnion() {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.UnionToken(Token.UNION);
+ }
+ static Token createEmpty() {
+ return Token.token_empty;
+ }
+ static RangeToken createRange() {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new RangeToken(Token.RANGE);
+ }
+ static RangeToken createNRange() {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new RangeToken(Token.NRANGE);
+ }
+ static Token.CharToken createChar(int ch) {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.CharToken(Token.CHAR, ch);
+ }
+ static private Token.CharToken createAnchor(int ch) {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.CharToken(Token.ANCHOR, ch);
+ }
+ static Token.StringToken createBackReference(int refno) {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.StringToken(Token.BACKREFERENCE, null, refno);
+ }
+ static Token.StringToken createString(String str) {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.StringToken(Token.STRING, str, 0);
+ }
+ static Token.ModifierToken createModifierGroup(Token child, int add, int mask) {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.ModifierToken(child, add, mask);
+ }
+ static Token.ConditionToken createCondition(int refno, Token condition,
+ Token yespat, Token nopat) {
+ if (COUNTTOKENS) Token.tokens ++;
+ return new Token.ConditionToken(refno, condition, yespat, nopat);
+ }
+
+ protected Token(int type) {
+ this.type = type;
+ }
+
+ /**
+ * A number of children.
+ */
+ int size() {
+ return 0;
+ }
+ Token getChild(int index) {
+ return null;
+ }
+ void addChild(Token tok) {
+ throw new RuntimeException("Not supported.");
+ }
+
+ // for RANGE or NRANGE
+ protected void addRange(int start, int end) {
+ throw new RuntimeException("Not supported.");
+ }
+ protected void sortRanges() {
+ throw new RuntimeException("Not supported.");
+ }
+ protected void compactRanges() {
+ throw new RuntimeException("Not supported.");
+ }
+ protected void mergeRanges(Token tok) {
+ throw new RuntimeException("Not supported.");
+ }
+ protected void subtractRanges(Token tok) {
+ throw new RuntimeException("Not supported.");
+ }
+ protected void intersectRanges(Token tok) {
+ throw new RuntimeException("Not supported.");
+ }
+ static Token complementRanges(Token tok) {
+ return RangeToken.complementRanges(tok);
+ }
+
+
+ void setMin(int min) { // for CLOSURE
+ }
+ void setMax(int max) { // for CLOSURE
+ }
+ int getMin() { // for CLOSURE
+ return -1;
+ }
+ int getMax() { // for CLOSURE
+ return -1;
+ }
+ int getReferenceNumber() { // for STRING
+ return 0;
+ }
+ String getString() { // for STRING
+ return null;
+ }
+
+ int getParenNumber() {
+ return 0;
+ }
+ int getChar() {
+ return -1;
+ }
+
+ public String toString() {
+ return this.toString(0);
+ }
+ public String toString(int options) {
+ return this.type == Token.DOT ? "." : "";
+ }
+
+ /**
+ * How many characters are needed?
+ */
+ final int getMinLength() {
+ switch (this.type) {
+ case CONCAT:
+ int sum = 0;
+ for (int i = 0; i < this.size(); i ++)
+ sum += this.getChild(i).getMinLength();
+ return sum;
+
+ case CONDITION:
+ case UNION:
+ if (this.size() == 0)
+ return 0;
+ int ret = this.getChild(0).getMinLength();
+ for (int i = 1; i < this.size(); i ++) {
+ int min = this.getChild(i).getMinLength();
+ if (min < ret) ret = min;
+ }
+ return ret;
+
+ case CLOSURE:
+ case NONGREEDYCLOSURE:
+ if (this.getMin() >= 0)
+ return this.getMin() * this.getChild(0).getMinLength();
+ return 0;
+
+ case EMPTY:
+ case ANCHOR:
+ return 0;
+
+ case DOT:
+ case CHAR:
+ case RANGE:
+ case NRANGE:
+ return 1;
+
+ case INDEPENDENT:
+ case PAREN:
+ case MODIFIERGROUP:
+ return this.getChild(0).getMinLength();
+
+ case BACKREFERENCE:
+ return 0; // *******
+
+ case STRING:
+ return this.getString().length();
+
+ case LOOKAHEAD:
+ case NEGATIVELOOKAHEAD:
+ case LOOKBEHIND:
+ case NEGATIVELOOKBEHIND:
+ return 0; // ***** Really?
+
+ default:
+ throw new RuntimeException("Token#getMinLength(): Invalid Type: "+this.type);
+ }
+ }
+
+ final int getMaxLength() {
+ switch (this.type) {
+ case CONCAT:
+ int sum = 0;
+ for (int i = 0; i < this.size(); i ++) {
+ int d = this.getChild(i).getMaxLength();
+ if (d < 0) return -1;
+ sum += d;
+ }
+ return sum;
+
+ case CONDITION:
+ case UNION:
+ if (this.size() == 0)
+ return 0;
+ int ret = this.getChild(0).getMaxLength();
+ for (int i = 1; ret >= 0 && i < this.size(); i ++) {
+ int max = this.getChild(i).getMaxLength();
+ if (max < 0) { // infinity
+ ret = -1;
+ break;
+ }
+ if (max > ret) ret = max;
+ }
+ return ret;
+
+ case CLOSURE:
+ case NONGREEDYCLOSURE:
+ if (this.getMax() >= 0)
+ // When this.child.getMaxLength() < 0,
+ // this returns minus value
+ return this.getMax() * this.getChild(0).getMaxLength();
+ return -1;
+
+ case EMPTY:
+ case ANCHOR:
+ return 0;
+
+ case CHAR:
+ return 1;
+ case DOT:
+ case RANGE:
+ case NRANGE:
+ return 2;
+
+ case INDEPENDENT:
+ case PAREN:
+ case MODIFIERGROUP:
+ return this.getChild(0).getMaxLength();
+
+ case BACKREFERENCE:
+ return -1; // ******
+
+ case STRING:
+ return this.getString().length();
+
+ case LOOKAHEAD:
+ case NEGATIVELOOKAHEAD:
+ case LOOKBEHIND:
+ case NEGATIVELOOKBEHIND:
+ return 0; // ***** Really?
+
+ default:
+ throw new RuntimeException("Token#getMaxLength(): Invalid Type: "+this.type);
+ }
+ }
+
+ static final int FC_CONTINUE = 0;
+ static final int FC_TERMINAL = 1;
+ static final int FC_ANY = 2;
+ private static final boolean isSet(int options, int flag) {
+ return (options & flag) == flag;
+ }
+ final int analyzeFirstCharacter(RangeToken result, int options) {
+ switch (this.type) {
+ case CONCAT:
+ int ret = FC_CONTINUE;
+ for (int i = 0; i < this.size(); i ++)
+ if ((ret = this.getChild(i).analyzeFirstCharacter(result, options)) != FC_CONTINUE)
+ break;
+ return ret;
+
+ case UNION:
+ if (this.size() == 0)
+ return FC_CONTINUE;
+ /*
+ * a|b|c -> FC_TERMINAL
+ * a|.|c -> FC_ANY
+ * a|b| -> FC_CONTINUE
+ */
+ int ret2 = FC_CONTINUE;
+ boolean hasEmpty = false;
+ for (int i = 0; i < this.size(); i ++) {
+ ret2 = this.getChild(i).analyzeFirstCharacter(result, options);
+ if (ret2 == FC_ANY)
+ break;
+ else if (ret2 == FC_CONTINUE)
+ hasEmpty = true;
+ }
+ return hasEmpty ? FC_CONTINUE : ret2;
+
+ case CONDITION:
+ int ret3 = this.getChild(0).analyzeFirstCharacter(result, options);
+ if (this.size() == 1) return FC_CONTINUE;
+ if (ret3 == FC_ANY) return ret3;
+ int ret4 = this.getChild(1).analyzeFirstCharacter(result, options);
+ if (ret4 == FC_ANY) return ret4;
+ return ret3 == FC_CONTINUE || ret4 == FC_CONTINUE ? FC_CONTINUE : FC_TERMINAL;
+
+ case CLOSURE:
+ case NONGREEDYCLOSURE:
+ this.getChild(0).analyzeFirstCharacter(result, options);
+ return FC_CONTINUE;
+
+ case EMPTY:
+ case ANCHOR:
+ return FC_CONTINUE;
+
+ case CHAR:
+ int ch = this.getChar();
+ result.addRange(ch, ch);
+ if (ch < 0x10000 && isSet(options, RegularExpression.IGNORE_CASE)) {
+ ch = Character.toUpperCase((char)ch);
+ result.addRange(ch, ch);
+ ch = Character.toLowerCase((char)ch);
+ result.addRange(ch, ch);
+ }
+ return FC_TERMINAL;
+
+ case DOT:
+ return FC_ANY;
+
+ case RANGE:
+ result.mergeRanges(this);
+ return FC_TERMINAL;
+
+ case NRANGE: // ****
+ result.mergeRanges(Token.complementRanges(this));
+ return FC_TERMINAL;
+
+ case INDEPENDENT:
+ case PAREN:
+ return this.getChild(0).analyzeFirstCharacter(result, options);
+
+ case MODIFIERGROUP:
+ options |= ((ModifierToken)this).getOptions();
+ options &= ~((ModifierToken)this).getOptionsMask();
+ return this.getChild(0).analyzeFirstCharacter(result, options);
+
+ case BACKREFERENCE:
+ result.addRange(0, UTF16_MAX); // **** We can not optimize.
+ return FC_ANY;
+
+ case STRING:
+ int cha = this.getString().charAt(0);
+ int ch2;
+ if (REUtil.isHighSurrogate(cha)
+ && this.getString().length() >= 2
+ && REUtil.isLowSurrogate((ch2 = this.getString().charAt(1))))
+ cha = REUtil.composeFromSurrogates(cha, ch2);
+ result.addRange(cha, cha);
+ if (cha < 0x10000 && isSet(options, RegularExpression.IGNORE_CASE)) {
+ cha = Character.toUpperCase((char)cha);
+ result.addRange(cha, cha);
+ cha = Character.toLowerCase((char)cha);
+ result.addRange(cha, cha);
+ }
+ return FC_TERMINAL;
+
+ case LOOKAHEAD:
+ case NEGATIVELOOKAHEAD:
+ case LOOKBEHIND:
+ case NEGATIVELOOKBEHIND:
+ return FC_CONTINUE;
+
+ default:
+ throw new RuntimeException("Token#analyzeHeadCharacter(): Invalid Type: "+this.type);
+ }
+ }
+
+ private final boolean isShorterThan(Token tok) {
+ if (tok == null) return false;
+ /*
+ int mylength;
+ if (this.type == STRING) mylength = this.getString().length();
+ else if (this.type == CHAR) mylength = this.getChar() >= 0x10000 ? 2 : 1;
+ else throw new RuntimeException("Internal Error: Illegal type: "+this.type);
+ int otherlength;
+ if (tok.type == STRING) otherlength = tok.getString().length();
+ else if (tok.type == CHAR) otherlength = tok.getChar() >= 0x10000 ? 2 : 1;
+ else throw new RuntimeException("Internal Error: Illegal type: "+tok.type);
+ */
+ int mylength;
+ if (this.type == STRING) mylength = this.getString().length();
+ else throw new RuntimeException("Internal Error: Illegal type: "+this.type);
+ int otherlength;
+ if (tok.type == STRING) otherlength = tok.getString().length();
+ else throw new RuntimeException("Internal Error: Illegal type: "+tok.type);
+ return mylength < otherlength;
+ }
+
+ static class FixedStringContainer {
+ Token token = null;
+ int options = 0;
+ FixedStringContainer() {
+ }
+ }
+
+ final void findFixedString(FixedStringContainer container, int options) {
+ switch (this.type) {
+ case CONCAT:
+ Token prevToken = null;
+ int prevOptions = 0;
+ for (int i = 0; i < this.size(); i ++) {
+ this.getChild(i).findFixedString(container, options);
+ if (prevToken == null || prevToken.isShorterThan(container.token)) {
+ prevToken = container.token;
+ prevOptions = container.options;
+ }
+ }
+ container.token = prevToken;
+ container.options = prevOptions;
+ return;
+
+ case UNION:
+ case CLOSURE:
+ case NONGREEDYCLOSURE:
+ case EMPTY:
+ case ANCHOR:
+ case RANGE:
+ case DOT:
+ case NRANGE:
+ case BACKREFERENCE:
+ case LOOKAHEAD:
+ case NEGATIVELOOKAHEAD:
+ case LOOKBEHIND:
+ case NEGATIVELOOKBEHIND:
+ case CONDITION:
+ container.token = null;
+ return;
+
+ case CHAR: // Ignore CHAR tokens.
+ container.token = null; // **
+ return; // **
+
+ case STRING:
+ container.token = this;
+ container.options = options;
+ return;
+
+ case INDEPENDENT:
+ case PAREN:
+ this.getChild(0).findFixedString(container, options);
+ return;
+
+ case MODIFIERGROUP:
+ options |= ((ModifierToken)this).getOptions();
+ options &= ~((ModifierToken)this).getOptionsMask();
+ this.getChild(0).findFixedString(container, options);
+ return;
+
+ default:
+ throw new RuntimeException("Token#findFixedString(): Invalid Type: "+this.type);
+ }
+ }
+
+ boolean match(int ch) {
+ throw new RuntimeException("NFAArrow#match(): Internal error: "+this.type);
+ }
+
+ // ------------------------------------------------------
+ private final static Hashtable categories = new Hashtable();
+ private final static Hashtable categories2 = new Hashtable();
+ private static final String[] categoryNames = {
+ "Cn", "Lu", "Ll", "Lt", "Lm", "Lo", "Mn", "Me", "Mc", "Nd",
+ "Nl", "No", "Zs", "Zl", "Zp", "Cc", "Cf", null, "Co", "Cs",
+ "Pd", "Ps", "Pe", "Pc", "Po", "Sm", "Sc", "Sk", "So", // 28
+ "Pi", "Pf", // 29, 30
+ "L", "M", "N", "Z", "C", "P", "S", // 31-37
+ };
+
+ // Schema Rec. {Datatypes} - Punctuation
+ static final int CHAR_INIT_QUOTE = 29; // Pi - initial quote
+ static final int CHAR_FINAL_QUOTE = 30; // Pf - final quote
+ static final int CHAR_LETTER = 31;
+ static final int CHAR_MARK = 32;
+ static final int CHAR_NUMBER = 33;
+ static final int CHAR_SEPARATOR = 34;
+ static final int CHAR_OTHER = 35;
+ static final int CHAR_PUNCTUATION = 36;
+ static final int CHAR_SYMBOL = 37;
+
+ //blockNames in UNICODE 3.1 that supported by XML Schema REC
+ private static final String[] blockNames = {
+ /*0000..007F;*/ "Basic Latin",
+ /*0080..00FF;*/ "Latin-1 Supplement",
+ /*0100..017F;*/ "Latin Extended-A",
+ /*0180..024F;*/ "Latin Extended-B",
+ /*0250..02AF;*/ "IPA Extensions",
+ /*02B0..02FF;*/ "Spacing Modifier Letters",
+ /*0300..036F;*/ "Combining Diacritical Marks",
+ /*0370..03FF;*/ "Greek",
+ /*0400..04FF;*/ "Cyrillic",
+ /*0530..058F;*/ "Armenian",
+ /*0590..05FF;*/ "Hebrew",
+ /*0600..06FF;*/ "Arabic",
+ /*0700..074F;*/ "Syriac",
+ /*0780..07BF;*/ "Thaana",
+ /*0900..097F;*/ "Devanagari",
+ /*0980..09FF;*/ "Bengali",
+ /*0A00..0A7F;*/ "Gurmukhi",
+ /*0A80..0AFF;*/ "Gujarati",
+ /*0B00..0B7F;*/ "Oriya",
+ /*0B80..0BFF;*/ "Tamil",
+ /*0C00..0C7F;*/ "Telugu",
+ /*0C80..0CFF;*/ "Kannada",
+ /*0D00..0D7F;*/ "Malayalam",
+ /*0D80..0DFF;*/ "Sinhala",
+ /*0E00..0E7F;*/ "Thai",
+ /*0E80..0EFF;*/ "Lao",
+ /*0F00..0FFF;*/ "Tibetan",
+ /*1000..109F;*/ "Myanmar",
+ /*10A0..10FF;*/ "Georgian",
+ /*1100..11FF;*/ "Hangul Jamo",
+ /*1200..137F;*/ "Ethiopic",
+ /*13A0..13FF;*/ "Cherokee",
+ /*1400..167F;*/ "Unified Canadian Aboriginal Syllabics",
+ /*1680..169F;*/ "Ogham",
+ /*16A0..16FF;*/ "Runic",
+ /*1780..17FF;*/ "Khmer",
+ /*1800..18AF;*/ "Mongolian",
+ /*1E00..1EFF;*/ "Latin Extended Additional",
+ /*1F00..1FFF;*/ "Greek Extended",
+ /*2000..206F;*/ "General Punctuation",
+ /*2070..209F;*/ "Superscripts and Subscripts",
+ /*20A0..20CF;*/ "Currency Symbols",
+ /*20D0..20FF;*/ "Combining Marks for Symbols",
+ /*2100..214F;*/ "Letterlike Symbols",
+ /*2150..218F;*/ "Number Forms",
+ /*2190..21FF;*/ "Arrows",
+ /*2200..22FF;*/ "Mathematical Operators",
+ /*2300..23FF;*/ "Miscellaneous Technical",
+ /*2400..243F;*/ "Control Pictures",
+ /*2440..245F;*/ "Optical Character Recognition",
+ /*2460..24FF;*/ "Enclosed Alphanumerics",
+ /*2500..257F;*/ "Box Drawing",
+ /*2580..259F;*/ "Block Elements",
+ /*25A0..25FF;*/ "Geometric Shapes",
+ /*2600..26FF;*/ "Miscellaneous Symbols",
+ /*2700..27BF;*/ "Dingbats",
+ /*2800..28FF;*/ "Braille Patterns",
+ /*2E80..2EFF;*/ "CJK Radicals Supplement",
+ /*2F00..2FDF;*/ "Kangxi Radicals",
+ /*2FF0..2FFF;*/ "Ideographic Description Characters",
+ /*3000..303F;*/ "CJK Symbols and Punctuation",
+ /*3040..309F;*/ "Hiragana",
+ /*30A0..30FF;*/ "Katakana",
+ /*3100..312F;*/ "Bopomofo",
+ /*3130..318F;*/ "Hangul Compatibility Jamo",
+ /*3190..319F;*/ "Kanbun",
+ /*31A0..31BF;*/ "Bopomofo Extended",
+ /*3200..32FF;*/ "Enclosed CJK Letters and Months",
+ /*3300..33FF;*/ "CJK Compatibility",
+ /*3400..4DB5;*/ "CJK Unified Ideographs Extension A",
+ /*4E00..9FFF;*/ "CJK Unified Ideographs",
+ /*A000..A48F;*/ "Yi Syllables",
+ /*A490..A4CF;*/ "Yi Radicals",
+ /*AC00..D7A3;*/ "Hangul Syllables",
+ /*E000..F8FF;*/ "Private Use",
+ /*F900..FAFF;*/ "CJK Compatibility Ideographs",
+ /*FB00..FB4F;*/ "Alphabetic Presentation Forms",
+ /*FB50..FDFF;*/ "Arabic Presentation Forms-A",
+ /*FE20..FE2F;*/ "Combining Half Marks",
+ /*FE30..FE4F;*/ "CJK Compatibility Forms",
+ /*FE50..FE6F;*/ "Small Form Variants",
+ /*FE70..FEFE;*/ "Arabic Presentation Forms-B",
+ /*FEFF..FEFF;*/ "Specials",
+ /*FF00..FFEF;*/ "Halfwidth and Fullwidth Forms",
+ //missing Specials add manually
+ /*10300..1032F;*/ "Old Italic", // 84
+ /*10330..1034F;*/ "Gothic",
+ /*10400..1044F;*/ "Deseret",
+ /*1D000..1D0FF;*/ "Byzantine Musical Symbols",
+ /*1D100..1D1FF;*/ "Musical Symbols",
+ /*1D400..1D7FF;*/ "Mathematical Alphanumeric Symbols",
+ /*20000..2A6D6;*/ "CJK Unified Ideographs Extension B",
+ /*2F800..2FA1F;*/ "CJK Compatibility Ideographs Supplement",
+ /*E0000..E007F;*/ "Tags",
+ //missing 2 private use add manually
+
+ };
+ //ADD THOSE MANUALLY
+ //F0000..FFFFD; "Private Use",
+ //100000..10FFFD; "Private Use"
+ //FFF0..FFFD; "Specials",
+ static final String blockRanges =
+ "\u0000\u007F\u0080\u00FF\u0100\u017F\u0180\u024F\u0250\u02AF\u02B0\u02FF\u0300\u036F"
+ +"\u0370\u03FF\u0400\u04FF\u0530\u058F\u0590\u05FF\u0600\u06FF\u0700\u074F\u0780\u07BF"
+ +"\u0900\u097F\u0980\u09FF\u0A00\u0A7F\u0A80\u0AFF\u0B00\u0B7F\u0B80\u0BFF\u0C00\u0C7F\u0C80\u0CFF"
+ +"\u0D00\u0D7F\u0D80\u0DFF\u0E00\u0E7F\u0E80\u0EFF\u0F00\u0FFF\u1000\u109F\u10A0\u10FF\u1100\u11FF"
+ +"\u1200\u137F\u13A0\u13FF\u1400\u167F\u1680\u169F\u16A0\u16FF\u1780\u17FF\u1800\u18AF\u1E00\u1EFF"
+ +"\u1F00\u1FFF\u2000\u206F\u2070\u209F\u20A0\u20CF\u20D0\u20FF\u2100\u214F\u2150\u218F\u2190\u21FF\u2200\u22FF"
+ +"\u2300\u23FF\u2400\u243F\u2440\u245F\u2460\u24FF\u2500\u257F\u2580\u259F\u25A0\u25FF\u2600\u26FF\u2700\u27BF"
+ +"\u2800\u28FF\u2E80\u2EFF\u2F00\u2FDF\u2FF0\u2FFF\u3000\u303F\u3040\u309F\u30A0\u30FF\u3100\u312F\u3130\u318F"
+ +"\u3190\u319F\u31A0\u31BF\u3200\u32FF\u3300\u33FF\u3400\u4DB5\u4E00\u9FFF\uA000\uA48F\uA490\uA4CF"
+ +"\uAC00\uD7A3\uE000\uF8FF\uF900\uFAFF\uFB00\uFB4F\uFB50\uFDFF"
+ +"\uFE20\uFE2F\uFE30\uFE4F\uFE50\uFE6F\uFE70\uFEFE\uFEFF\uFEFF\uFF00\uFFEF";
+ static final int[] nonBMPBlockRanges = {
+ 0x10300, 0x1032F, // 84
+ 0x10330, 0x1034F,
+ 0x10400, 0x1044F,
+ 0x1D000, 0x1D0FF,
+ 0x1D100, 0x1D1FF,
+ 0x1D400, 0x1D7FF,
+ 0x20000, 0x2A6D6,
+ 0x2F800, 0x2FA1F,
+ 0xE0000, 0xE007F
+ };
+ private static final int NONBMP_BLOCK_START = 84;
+
+ static protected RangeToken getRange(String name, boolean positive) {
+ if (Token.categories.size() == 0) {
+ synchronized (Token.categories) {
+ Token[] ranges = new Token[Token.categoryNames.length];
+ for (int i = 0; i < ranges.length; i ++) {
+ ranges[i] = Token.createRange();
+ }
+ int type;
+ for (int i = 0; i < 0x10000; i ++) {
+ type = Character.getType((char)i);
+ if (type == Character.START_PUNCTUATION ||
+ type == Character.END_PUNCTUATION) {
+ //build table of Pi values
+ if (i == 0x00AB || i == 0x2018 || i == 0x201B || i == 0x201C ||
+ i == 0x201F || i == 0x2039) {
+ type = CHAR_INIT_QUOTE;
+ }
+ //build table of Pf values
+ if (i == 0x00BB || i == 0x2019 || i == 0x201D || i == 0x203A ) {
+ type = CHAR_FINAL_QUOTE;
+ }
+ }
+ ranges[type].addRange(i, i);
+ switch (type) {
+ case Character.UPPERCASE_LETTER:
+ case Character.LOWERCASE_LETTER:
+ case Character.TITLECASE_LETTER:
+ case Character.MODIFIER_LETTER:
+ case Character.OTHER_LETTER:
+ type = CHAR_LETTER;
+ break;
+ case Character.NON_SPACING_MARK:
+ case Character.COMBINING_SPACING_MARK:
+ case Character.ENCLOSING_MARK:
+ type = CHAR_MARK;
+ break;
+ case Character.DECIMAL_DIGIT_NUMBER:
+ case Character.LETTER_NUMBER:
+ case Character.OTHER_NUMBER:
+ type = CHAR_NUMBER;
+ break;
+ case Character.SPACE_SEPARATOR:
+ case Character.LINE_SEPARATOR:
+ case Character.PARAGRAPH_SEPARATOR:
+ type = CHAR_SEPARATOR;
+ break;
+ case Character.CONTROL:
+ case Character.FORMAT:
+ case Character.SURROGATE:
+ case Character.PRIVATE_USE:
+ case Character.UNASSIGNED:
+ type = CHAR_OTHER;
+ break;
+ case Character.CONNECTOR_PUNCTUATION:
+ case Character.DASH_PUNCTUATION:
+ case Character.START_PUNCTUATION:
+ case Character.END_PUNCTUATION:
+ case CHAR_INIT_QUOTE:
+ case CHAR_FINAL_QUOTE:
+ case Character.OTHER_PUNCTUATION:
+ type = CHAR_PUNCTUATION;
+ break;
+ case Character.MATH_SYMBOL:
+ case Character.CURRENCY_SYMBOL:
+ case Character.MODIFIER_SYMBOL:
+ case Character.OTHER_SYMBOL:
+ type = CHAR_SYMBOL;
+ break;
+ default:
+ throw new RuntimeException("org.apache.xerces.utils.regex.Token#getRange(): Unknown Unicode category: "+type);
+ }
+ ranges[type].addRange(i, i);
+ } // for all characters
+ ranges[Character.UNASSIGNED].addRange(0x10000, Token.UTF16_MAX);
+ ranges[CHAR_OTHER].addRange(0x10000, Token.UTF16_MAX);
+
+ for (int i = 0; i < ranges.length; i ++) {
+ if (Token.categoryNames[i] != null) {
+ if (i == Character.UNASSIGNED) { // Unassigned
+ ranges[i].addRange(0x10000, Token.UTF16_MAX);
+ }
+ Token.categories.put(Token.categoryNames[i], ranges[i]);
+ Token.categories2.put(Token.categoryNames[i],
+ Token.complementRanges(ranges[i]));
+ }
+ }
+ //REVISIT: do we really need to support block names as in Unicode 3.1
+ // or we can just create all the names in IsBLOCKNAME format (XML Schema REC)?
+ //
+ StringBuffer buffer = new StringBuffer(50);
+ for (int i = 0; i < Token.blockNames.length; i ++) {
+ Token r1 = Token.createRange();
+ int location;
+ if (i < NONBMP_BLOCK_START) {
+ location = i*2;
+ int rstart = Token.blockRanges.charAt(location);
+ int rend = Token.blockRanges.charAt(location+1);
+ //DEBUGING
+ //System.out.println(n+" " +Integer.toHexString(rstart)
+ // +"-"+ Integer.toHexString(rend));
+ r1.addRange(rstart, rend);
+ } else {
+ location = (i - NONBMP_BLOCK_START) * 2;
+ r1.addRange(Token.nonBMPBlockRanges[location],
+ Token.nonBMPBlockRanges[location + 1]);
+ }
+ String n = Token.blockNames[i];
+ if (n.equals("Specials"))
+ r1.addRange(0xfff0, 0xfffd);
+ if (n.equals("Private Use")) {
+ r1.addRange(0xF0000,0xFFFFD);
+ r1.addRange(0x100000,0x10FFFD);
+ }
+ Token.categories.put(n, r1);
+ Token.categories2.put(n, Token.complementRanges(r1));
+ buffer.setLength(0);
+ buffer.append("Is");
+ if (n.indexOf(' ') >= 0) {
+ for (int ci = 0; ci < n.length(); ci ++)
+ if (n.charAt(ci) != ' ') buffer.append((char)n.charAt(ci));
+ }
+ else {
+ buffer.append(n);
+ }
+ Token.setAlias(buffer.toString(), n, true);
+ }
+
+ // TR#18 1.2
+ Token.setAlias("ASSIGNED", "Cn", false);
+ Token.setAlias("UNASSIGNED", "Cn", true);
+ Token all = Token.createRange();
+ all.addRange(0, Token.UTF16_MAX);
+ Token.categories.put("ALL", all);
+ Token.categories2.put("ALL", Token.complementRanges(all));
+ Token.registerNonXS("ASSIGNED");
+ Token.registerNonXS("UNASSIGNED");
+ Token.registerNonXS("ALL");
+
+ Token isalpha = Token.createRange();
+ isalpha.mergeRanges(ranges[Character.UPPERCASE_LETTER]); // Lu
+ isalpha.mergeRanges(ranges[Character.LOWERCASE_LETTER]); // Ll
+ isalpha.mergeRanges(ranges[Character.OTHER_LETTER]); // Lo
+ Token.categories.put("IsAlpha", isalpha);
+ Token.categories2.put("IsAlpha", Token.complementRanges(isalpha));
+ Token.registerNonXS("IsAlpha");
+
+ Token isalnum = Token.createRange();
+ isalnum.mergeRanges(isalpha); // Lu Ll Lo
+ isalnum.mergeRanges(ranges[Character.DECIMAL_DIGIT_NUMBER]); // Nd
+ Token.categories.put("IsAlnum", isalnum);
+ Token.categories2.put("IsAlnum", Token.complementRanges(isalnum));
+ Token.registerNonXS("IsAlnum");
+
+ Token isspace = Token.createRange();
+ isspace.mergeRanges(Token.token_spaces);
+ isspace.mergeRanges(ranges[CHAR_SEPARATOR]); // Z
+ Token.categories.put("IsSpace", isspace);
+ Token.categories2.put("IsSpace", Token.complementRanges(isspace));
+ Token.registerNonXS("IsSpace");
+
+ Token isword = Token.createRange();
+ isword.mergeRanges(isalnum); // Lu Ll Lo Nd
+ isword.addRange('_', '_');
+ Token.categories.put("IsWord", isword);
+ Token.categories2.put("IsWord", Token.complementRanges(isword));
+ Token.registerNonXS("IsWord");
+
+ Token isascii = Token.createRange();
+ isascii.addRange(0, 127);
+ Token.categories.put("IsASCII", isascii);
+ Token.categories2.put("IsASCII", Token.complementRanges(isascii));
+ Token.registerNonXS("IsASCII");
+
+ Token isnotgraph = Token.createRange();
+ isnotgraph.mergeRanges(ranges[CHAR_OTHER]);
+ isnotgraph.addRange(' ', ' ');
+ Token.categories.put("IsGraph", Token.complementRanges(isnotgraph));
+ Token.categories2.put("IsGraph", isnotgraph);
+ Token.registerNonXS("IsGraph");
+
+ Token isxdigit = Token.createRange();
+ isxdigit.addRange('0', '9');
+ isxdigit.addRange('A', 'F');
+ isxdigit.addRange('a', 'f');
+ Token.categories.put("IsXDigit", Token.complementRanges(isxdigit));
+ Token.categories2.put("IsXDigit", isxdigit);
+ Token.registerNonXS("IsXDigit");
+
+ Token.setAlias("IsDigit", "Nd", true);
+ Token.setAlias("IsUpper", "Lu", true);
+ Token.setAlias("IsLower", "Ll", true);
+ Token.setAlias("IsCntrl", "C", true);
+ Token.setAlias("IsPrint", "C", false);
+ Token.setAlias("IsPunct", "P", true);
+ Token.registerNonXS("IsDigit");
+ Token.registerNonXS("IsUpper");
+ Token.registerNonXS("IsLower");
+ Token.registerNonXS("IsCntrl");
+ Token.registerNonXS("IsPrint");
+ Token.registerNonXS("IsPunct");
+
+ Token.setAlias("alpha", "IsAlpha", true);
+ Token.setAlias("alnum", "IsAlnum", true);
+ Token.setAlias("ascii", "IsASCII", true);
+ Token.setAlias("cntrl", "IsCntrl", true);
+ Token.setAlias("digit", "IsDigit", true);
+ Token.setAlias("graph", "IsGraph", true);
+ Token.setAlias("lower", "IsLower", true);
+ Token.setAlias("print", "IsPrint", true);
+ Token.setAlias("punct", "IsPunct", true);
+ Token.setAlias("space", "IsSpace", true);
+ Token.setAlias("upper", "IsUpper", true);
+ Token.setAlias("word", "IsWord", true); // Perl extension
+ Token.setAlias("xdigit", "IsXDigit", true);
+ Token.registerNonXS("alpha");
+ Token.registerNonXS("alnum");
+ Token.registerNonXS("ascii");
+ Token.registerNonXS("cntrl");
+ Token.registerNonXS("digit");
+ Token.registerNonXS("graph");
+ Token.registerNonXS("lower");
+ Token.registerNonXS("print");
+ Token.registerNonXS("punct");
+ Token.registerNonXS("space");
+ Token.registerNonXS("upper");
+ Token.registerNonXS("word");
+ Token.registerNonXS("xdigit");
+ } // synchronized
+ } // if null
+ RangeToken tok = positive ? (RangeToken)Token.categories.get(name)
+ : (RangeToken)Token.categories2.get(name);
+ //if (tok == null) System.out.println(name);
+ return tok;
+ }
+ static protected RangeToken getRange(String name, boolean positive, boolean xs) {
+ RangeToken range = Token.getRange(name, positive);
+ if (xs && range != null && Token.isRegisterNonXS(name))
+ range = null;
+ return range;
+ }
+
+ static Hashtable nonxs = null;
+ /**
+ * This method is called by only getRange().
+ * So this method need not MT-safe.
+ */
+ static protected void registerNonXS(String name) {
+ if (Token.nonxs == null)
+ Token.nonxs = new Hashtable();
+ Token.nonxs.put(name, name);
+ }
+ static protected boolean isRegisterNonXS(String name) {
+ if (Token.nonxs == null)
+ return false;
+ //DEBUG
+ //System.err.println("isRegisterNonXS: "+name);
+ return Token.nonxs.containsKey(name);
+ }
+
+ private static void setAlias(String newName, String name, boolean positive) {
+ Token t1 = (Token)Token.categories.get(name);
+ Token t2 = (Token)Token.categories2.get(name);
+ if (positive) {
+ Token.categories.put(newName, t1);
+ Token.categories2.put(newName, t2);
+ } else {
+ Token.categories2.put(newName, t1);
+ Token.categories.put(newName, t2);
+ }
+ }
+
+ // ------------------------------------------------------
+
+ static final String viramaString =
+ "\u094D"// ;DEVANAGARI SIGN VIRAMA;Mn;9;ON;;;;;N;;;;;
+ +"\u09CD"//;BENGALI SIGN VIRAMA;Mn;9;ON;;;;;N;;;;;
+ +"\u0A4D"//;GURMUKHI SIGN VIRAMA;Mn;9;ON;;;;;N;;;;;
+ +"\u0ACD"//;GUJARATI SIGN VIRAMA;Mn;9;ON;;;;;N;;;;;
+ +"\u0B4D"//;ORIYA SIGN VIRAMA;Mn;9;ON;;;;;N;;;;;
+ +"\u0BCD"//;TAMIL SIGN VIRAMA;Mn;9;ON;;;;;N;;;;;
+ +"\u0C4D"//;TELUGU SIGN VIRAMA;Mn;9;ON;;;;;N;;;;;
+ +"\u0CCD"//;KANNADA SIGN VIRAMA;Mn;9;ON;;;;;N;;;;;
+ +"\u0D4D"//;MALAYALAM SIGN VIRAMA;Mn;9;ON;;;;;N;;;;;
+ +"\u0E3A"//;THAI CHARACTER PHINTHU;Mn;9;ON;;;;;N;THAI VOWEL SIGN PHINTHU;;;;
+ +"\u0F84";//;TIBETAN MARK HALANTA;Mn;9;ON;;;;;N;TIBETAN VIRAMA;;;;
+
+ static private Token token_grapheme = null;
+ static synchronized Token getGraphemePattern() {
+ if (Token.token_grapheme != null)
+ return Token.token_grapheme;
+
+ Token base_char = Token.createRange(); // [{ASSIGNED}]-[{M},{C}]
+ base_char.mergeRanges(Token.getRange("ASSIGNED", true));
+ base_char.subtractRanges(Token.getRange("M", true));
+ base_char.subtractRanges(Token.getRange("C", true));
+
+ Token virama = Token.createRange();
+ for (int i = 0; i < Token.viramaString.length(); i++) {
+ virama.addRange(i, i);
+ }
+
+ Token combiner_wo_virama = Token.createRange();
+ combiner_wo_virama.mergeRanges(Token.getRange("M", true));
+ combiner_wo_virama.addRange(0x1160, 0x11ff); // hangul_medial and hangul_final
+ combiner_wo_virama.addRange(0xff9e, 0xff9f); // extras
+
+ Token left = Token.createUnion(); // base_char?
+ left.addChild(base_char);
+ left.addChild(Token.token_empty);
+
+ Token foo = Token.createUnion();
+ foo.addChild(Token.createConcat(virama, Token.getRange("L", true)));
+ foo.addChild(combiner_wo_virama);
+
+ foo = Token.createClosure(foo);
+
+ foo = Token.createConcat(left, foo);
+
+ Token.token_grapheme = foo;
+ return Token.token_grapheme;
+ }
+
+ /**
+ * Combing Character Sequence in Perl 5.6.
+ */
+ static private Token token_ccs = null;
+ static synchronized Token getCombiningCharacterSequence() {
+ if (Token.token_ccs != null)
+ return Token.token_ccs;
+
+ Token foo = Token.createClosure(Token.getRange("M", true)); // \pM*
+ foo = Token.createConcat(Token.getRange("M", false), foo); // \PM + \pM*
+ Token.token_ccs = foo;
+ return Token.token_ccs;
+ }
+
+ // ------------------------------------------------------
+
+ // ------------------------------------------------------
+ /**
+ * This class represents a node in parse tree.
+ */
+ static class StringToken extends Token implements java.io.Serializable {
+
+ private static final long serialVersionUID = -4614366944218504172L;
+
+ String string;
+ final int refNumber;
+
+ StringToken(int type, String str, int n) {
+ super(type);
+ this.string = str;
+ this.refNumber = n;
+ }
+
+ int getReferenceNumber() { // for STRING
+ return this.refNumber;
+ }
+ String getString() { // for STRING
+ return this.string;
+ }
+
+ public String toString(int options) {
+ if (this.type == BACKREFERENCE)
+ return "\\"+this.refNumber;
+ else
+ return REUtil.quoteMeta(this.string);
+ }
+ }
+
+ /**
+ * This class represents a node in parse tree.
+ */
+ static class ConcatToken extends Token implements java.io.Serializable {
+
+ private static final long serialVersionUID = 8717321425541346381L;
+
+ final Token child;
+ final Token child2;
+
+ ConcatToken(Token t1, Token t2) {
+ super(Token.CONCAT);
+ this.child = t1;
+ this.child2 = t2;
+ }
+
+ int size() {
+ return 2;
+ }
+ Token getChild(int index) {
+ return index == 0 ? this.child : this.child2;
+ }
+
+ public String toString(int options) {
+ String ret;
+ if (this.child2.type == CLOSURE && this.child2.getChild(0) == this.child) {
+ ret = this.child.toString(options)+"+";
+ } else if (this.child2.type == NONGREEDYCLOSURE && this.child2.getChild(0) == this.child) {
+ ret = this.child.toString(options)+"+?";
+ } else
+ ret = this.child.toString(options)+this.child2.toString(options);
+ return ret;
+ }
+ }
+
+ /**
+ * This class represents a node in parse tree.
+ */
+ static class CharToken extends Token implements java.io.Serializable {
+
+ private static final long serialVersionUID = -4394272816279496989L;
+
+ final int chardata;
+
+ CharToken(int type, int ch) {
+ super(type);
+ this.chardata = ch;
+ }
+
+ int getChar() {
+ return this.chardata;
+ }
+
+ public String toString(int options) {
+ String ret;
+ switch (this.type) {
+ case CHAR:
+ switch (this.chardata) {
+ case '|': case '*': case '+': case '?':
+ case '(': case ')': case '.': case '[':
+ case '{': case '\\':
+ ret = "\\"+(char)this.chardata;
+ break;
+ case '\f': ret = "\\f"; break;
+ case '\n': ret = "\\n"; break;
+ case '\r': ret = "\\r"; break;
+ case '\t': ret = "\\t"; break;
+ case 0x1b: ret = "\\e"; break;
+ //case 0x0b: ret = "\\v"; break;
+ default:
+ if (this.chardata >= 0x10000) {
+ String pre = "0"+Integer.toHexString(this.chardata);
+ ret = "\\v"+pre.substring(pre.length()-6, pre.length());
+ } else
+ ret = ""+(char)this.chardata;
+ }
+ break;
+
+ case ANCHOR:
+ if (this == Token.token_linebeginning || this == Token.token_lineend)
+ ret = ""+(char)this.chardata;
+ else
+ ret = "\\"+(char)this.chardata;
+ break;
+
+ default:
+ ret = null;
+ }
+ return ret;
+ }
+
+ boolean match(int ch) {
+ if (this.type == CHAR) {
+ return ch == this.chardata;
+ } else
+ throw new RuntimeException("NFAArrow#match(): Internal error: "+this.type);
+ }
+ }
+
+ /**
+ * This class represents a node in parse tree.
+ */
+ static class ClosureToken extends Token implements java.io.Serializable {
+
+ private static final long serialVersionUID = 1308971930673997452L;
+
+ int min;
+ int max;
+ final Token child;
+
+ ClosureToken(int type, Token tok) {
+ super(type);
+ this.child = tok;
+ this.setMin(-1);
+ this.setMax(-1);
+ }
+
+ int size() {
+ return 1;
+ }
+ Token getChild(int index) {
+ return this.child;
+ }
+
+ final void setMin(int min) {
+ this.min = min;
+ }
+ final void setMax(int max) {
+ this.max = max;
+ }
+ final int getMin() {
+ return this.min;
+ }
+ final int getMax() {
+ return this.max;
+ }
+
+ public String toString(int options) {
+ String ret;
+ if (this.type == CLOSURE) {
+ if (this.getMin() < 0 && this.getMax() < 0) {
+ ret = this.child.toString(options)+"*";
+ } else if (this.getMin() == this.getMax()) {
+ ret = this.child.toString(options)+"{"+this.getMin()+"}";
+ } else if (this.getMin() >= 0 && this.getMax() >= 0) {
+ ret = this.child.toString(options)+"{"+this.getMin()+","+this.getMax()+"}";
+ } else if (this.getMin() >= 0 && this.getMax() < 0) {
+ ret = this.child.toString(options)+"{"+this.getMin()+",}";
+ } else
+ throw new RuntimeException("Token#toString(): CLOSURE "
+ +this.getMin()+", "+this.getMax());
+ } else {
+ if (this.getMin() < 0 && this.getMax() < 0) {
+ ret = this.child.toString(options)+"*?";
+ } else if (this.getMin() == this.getMax()) {
+ ret = this.child.toString(options)+"{"+this.getMin()+"}?";
+ } else if (this.getMin() >= 0 && this.getMax() >= 0) {
+ ret = this.child.toString(options)+"{"+this.getMin()+","+this.getMax()+"}?";
+ } else if (this.getMin() >= 0 && this.getMax() < 0) {
+ ret = this.child.toString(options)+"{"+this.getMin()+",}?";
+ } else
+ throw new RuntimeException("Token#toString(): NONGREEDYCLOSURE "
+ +this.getMin()+", "+this.getMax());
+ }
+ return ret;
+ }
+ }
+
+ /**
+ * This class represents a node in parse tree.
+ */
+ static class ParenToken extends Token implements java.io.Serializable {
+
+ private static final long serialVersionUID = -5938014719827987704L;
+
+ final Token child;
+ final int parennumber;
+
+ ParenToken(int type, Token tok, int paren) {
+ super(type);
+ this.child = tok;
+ this.parennumber = paren;
+ }
+
+ int size() {
+ return 1;
+ }
+ Token getChild(int index) {
+ return this.child;
+ }
+
+ int getParenNumber() {
+ return this.parennumber;
+ }
+
+ public String toString(int options) {
+ String ret = null;
+ switch (this.type) {
+ case PAREN:
+ if (this.parennumber == 0) {
+ ret = "(?:"+this.child.toString(options)+")";
+ } else {
+ ret = "("+this.child.toString(options)+")";
+ }
+ break;
+
+ case LOOKAHEAD:
+ ret = "(?="+this.child.toString(options)+")";
+ break;
+ case NEGATIVELOOKAHEAD:
+ ret = "(?!"+this.child.toString(options)+")";
+ break;
+ case LOOKBEHIND:
+ ret = "(?<="+this.child.toString(options)+")";
+ break;
+ case NEGATIVELOOKBEHIND:
+ ret = "(?"+this.child.toString(options)+")";
+ break;
+ }
+ return ret;
+ }
+ }
+
+ /**
+ * (?(condition)yes-pattern|no-pattern)
+ */
+ static class ConditionToken extends Token implements java.io.Serializable {
+
+ private static final long serialVersionUID = 4353765277910594411L;
+
+ final int refNumber;
+ final Token condition;
+ final Token yes;
+ final Token no;
+ ConditionToken(int refno, Token cond, Token yespat, Token nopat) {
+ super(Token.CONDITION);
+ this.refNumber = refno;
+ this.condition = cond;
+ this.yes = yespat;
+ this.no = nopat;
+ }
+ int size() {
+ return this.no == null ? 1 : 2;
+ }
+ Token getChild(int index) {
+ if (index == 0) return this.yes;
+ if (index == 1) return this.no;
+ throw new RuntimeException("Internal Error: "+index);
+ }
+
+ public String toString(int options) {
+ String ret;
+ if (refNumber > 0) {
+ ret = "(?("+refNumber+")";
+ } else if (this.condition.type == Token.ANCHOR) {
+ ret = "(?("+this.condition+")";
+ } else {
+ ret = "(?"+this.condition;
+ }
+
+ if (this.no == null) {
+ ret += this.yes+")";
+ } else {
+ ret += this.yes+"|"+this.no+")";
+ }
+ return ret;
+ }
+ }
+
+ /**
+ * (ims-ims: .... )
+ */
+ static class ModifierToken extends Token implements java.io.Serializable {
+
+ private static final long serialVersionUID = -9114536559696480356L;
+
+ final Token child;
+ final int add;
+ final int mask;
+
+ ModifierToken(Token tok, int add, int mask) {
+ super(Token.MODIFIERGROUP);
+ this.child = tok;
+ this.add = add;
+ this.mask = mask;
+ }
+
+ int size() {
+ return 1;
+ }
+ Token getChild(int index) {
+ return this.child;
+ }
+
+ int getOptions() {
+ return this.add;
+ }
+ int getOptionsMask() {
+ return this.mask;
+ }
+
+ public String toString(int options) {
+ return "(?"
+ +(this.add == 0 ? "" : REUtil.createOptionString(this.add))
+ +(this.mask == 0 ? "" : REUtil.createOptionString(this.mask))
+ +":"
+ +this.child.toString(options)
+ +")";
+ }
+ }
+
+ /**
+ * This class represents a node in parse tree.
+ * for UNION or CONCAT.
+ */
+ static class UnionToken extends Token implements java.io.Serializable {
+
+ private static final long serialVersionUID = -2568843945989489861L;
+
+ Vector children;
+
+ UnionToken(int type) {
+ super(type);
+ }
+
+ void addChild(Token tok) {
+ if (tok == null) return;
+ if (this.children == null) this.children = new Vector();
+ if (this.type == UNION) {
+ this.children.addElement(tok);
+ return;
+ }
+ // This is CONCAT, and new child is CONCAT.
+ if (tok.type == CONCAT) {
+ for (int i = 0; i < tok.size(); i ++)
+ this.addChild(tok.getChild(i)); // Recursion
+ return;
+ }
+ int size = this.children.size();
+ if (size == 0) {
+ this.children.addElement(tok);
+ return;
+ }
+ Token previous = (Token)this.children.elementAt(size-1);
+ if (!((previous.type == CHAR || previous.type == STRING)
+ && (tok.type == CHAR || tok.type == STRING))) {
+ this.children.addElement(tok);
+ return;
+ }
+
+ //System.err.println("Merge '"+previous+"' and '"+tok+"'.");
+
+ StringBuffer buffer;
+ int nextMaxLength = (tok.type == CHAR ? 2 : tok.getString().length());
+ if (previous.type == CHAR) { // Replace previous token by STRING
+ buffer = new StringBuffer(2 + nextMaxLength);
+ int ch = previous.getChar();
+ if (ch >= 0x10000)
+ buffer.append(REUtil.decomposeToSurrogates(ch));
+ else
+ buffer.append((char)ch);
+ previous = Token.createString(null);
+ this.children.setElementAt(previous, size-1);
+ } else { // STRING
+ buffer = new StringBuffer(previous.getString().length() + nextMaxLength);
+ buffer.append(previous.getString());
+ }
+
+ if (tok.type == CHAR) {
+ int ch = tok.getChar();
+ if (ch >= 0x10000)
+ buffer.append(REUtil.decomposeToSurrogates(ch));
+ else
+ buffer.append((char)ch);
+ } else {
+ buffer.append(tok.getString());
+ }
+
+ ((StringToken)previous).string = new String(buffer);
+ }
+
+ int size() {
+ return this.children == null ? 0 : this.children.size();
+ }
+ Token getChild(int index) {
+ return (Token)this.children.elementAt(index);
+ }
+
+ public String toString(int options) {
+ String ret;
+ if (this.type == CONCAT) {
+ if (this.children.size() == 2) {
+ Token ch = this.getChild(0);
+ Token ch2 = this.getChild(1);
+ if (ch2.type == CLOSURE && ch2.getChild(0) == ch) {
+ ret = ch.toString(options)+"+";
+ } else if (ch2.type == NONGREEDYCLOSURE && ch2.getChild(0) == ch) {
+ ret = ch.toString(options)+"+?";
+ } else
+ ret = ch.toString(options)+ch2.toString(options);
+ } else {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < this.children.size(); i ++) {
+ sb.append(((Token)this.children.elementAt(i)).toString(options));
+ }
+ ret = new String(sb);
+ }
+ return ret;
+ }
+ if (this.children.size() == 2 && this.getChild(1).type == EMPTY) {
+ ret = this.getChild(0).toString(options)+"?";
+ } else if (this.children.size() == 2
+ && this.getChild(0).type == EMPTY) {
+ ret = this.getChild(1).toString(options)+"??";
+ } else {
+ StringBuffer sb = new StringBuffer();
+ sb.append(((Token)this.children.elementAt(0)).toString(options));
+ for (int i = 1; i < this.children.size(); i ++) {
+ sb.append((char)'|');
+ sb.append(((Token)this.children.elementAt(i)).toString(options));
+ }
+ ret = new String(sb);
+ }
+ return ret;
+ }
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/message.properties b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/message.properties
new file mode 100644
index 0000000..7e15bfe
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xpath/regex/message.properties
@@ -0,0 +1,58 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# @version $Id$
+
+parser.parse.1=Wrong character.
+parser.parse.2=Invalid reference number.
+parser.next.1=A character is required after \\.
+parser.next.2='?' is not expected. '(?:' or '(?=' or '(?!' or '(?<' or '(?#' or '(?>'?
+parser.next.3='(?<=' or '(?'?
+parser.next.3='(?<=' ou '(?'?
+parser.next.3='(?<=' \u307e\u305f\u306f '(? 0) {
+ final StringList errorMessages = attrPSVI.getErrorMessages();
+ final String[] errors = new String[length << 1];
+ for (int i = 0, j = 0; i < length; ++i) {
+ errors[j++] = errorCodes.item(i);
+ errors[j++] = errorMessages.item(i);
+ }
+ fErrors = errors;
+ }
+ }
+ fValidationContext = attrPSVI.getValidationContext();
+ fIsConstant = isConstant;
+ }
+
+ //
+ // AttributePSVI methods
+ //
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#constant()
+ */
+ public ItemPSVI constant() {
+ if (isConstant()) {
+ return this;
+ }
+ return new AttributePSVImpl(true, this);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#isConstant()
+ */
+ public boolean isConstant() {
+ return fIsConstant;
+ }
+
+ /**
+ * [schema default]
+ *
+ * @return The canonical lexical representation of the declaration's {value constraint} value.
+ * @see XML Schema Part 1: Structures [schema normalized value]
+ * @return the normalized value of this item after validation
+ */
+ public String getSchemaNormalizedValue() {
+ return fValue.getNormalizedValue();
+ }
+
+ /**
+ * [schema specified]
+ * @see XML Schema Part 1: Structures [schema specified]
+ * @return true - value was specified in schema, false - value comes from the infoset
+ */
+ public boolean getIsSchemaSpecified() {
+ return fSpecified;
+ }
+
+
+ /**
+ * Determines the extent to which the document has been validated
+ *
+ * @return return the [validation attempted] property. The possible values are
+ * NO_VALIDATION, PARTIAL_VALIDATION and FULL_VALIDATION
+ */
+ public short getValidationAttempted() {
+ return fValidationAttempted;
+ }
+
+ /**
+ * Determine the validity of the node with respect
+ * to the validation being attempted
+ *
+ * @return return the [validity] property. Possible values are:
+ * UNKNOWN_VALIDITY, INVALID_VALIDITY, VALID_VALIDITY
+ */
+ public short getValidity() {
+ return fValidity;
+ }
+
+ /**
+ * A list of error codes generated from validation attempts.
+ * Need to find all the possible subclause reports that need reporting
+ *
+ * @return list of error codes
+ */
+ public StringList getErrorCodes() {
+ if (fErrors == null || fErrors.length == 0) {
+ return StringListImpl.EMPTY_LIST;
+ }
+ return new PSVIErrorList(fErrors, true);
+ }
+
+ /**
+ * A list of error messages generated from the validation attempt or
+ * an empty StringList if no errors occurred during the
+ * validation attempt. The indices of error messages in this list are
+ * aligned with those in the [schema error code] list.
+ */
+ public StringList getErrorMessages() {
+ if (fErrors == null || fErrors.length == 0) {
+ return StringListImpl.EMPTY_LIST;
+ }
+ return new PSVIErrorList(fErrors, false);
+ }
+
+ // This is the only information we can provide in a pipeline.
+ public String getValidationContext() {
+ return fValidationContext;
+ }
+
+ /**
+ * An item isomorphic to the type definition used to validate this element.
+ *
+ * @return a type declaration
+ */
+ public XSTypeDefinition getTypeDefinition() {
+ return fTypeDecl;
+ }
+
+ /**
+ * If and only if that type definition is a simple type definition
+ * with {variety} union, or a complex type definition whose {content type}
+ * is a simple thype definition with {variety} union, then an item isomorphic
+ * to that member of the union's {member type definitions} which actually
+ * validated the element item's normalized value.
+ *
+ * @return a simple type declaration
+ */
+ public XSSimpleTypeDefinition getMemberTypeDefinition() {
+ return fValue.getMemberTypeDefinition();
+ }
+
+ /**
+ * An item isomorphic to the attribute declaration used to validate
+ * this attribute.
+ *
+ * @return an attribute declaration
+ */
+ public XSAttributeDeclaration getAttributeDeclaration() {
+ return fDeclaration;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getActualNormalizedValue()
+ */
+ public Object getActualNormalizedValue() {
+ return fValue.getActualValue();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getActualNormalizedValueType()
+ */
+ public short getActualNormalizedValueType() {
+ return fValue.getActualValueType();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getItemValueTypes()
+ */
+ public ShortList getItemValueTypes() {
+ return fValue.getListValueTypes();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getSchemaValue()
+ */
+ public XSValue getSchemaValue() {
+ return fValue;
+ }
+
+ /**
+ * Reset()
+ */
+ public void reset() {
+ fValue.reset();
+ fDeclaration = null;
+ fTypeDecl = null;
+ fSpecified = false;
+ fValidationAttempted = AttributePSVI.VALIDATION_NONE;
+ fValidity = AttributePSVI.VALIDITY_NOTKNOWN;
+ fErrors = null;
+ fValidationContext = null;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xs/ElementPSVImpl.java b/resources/xerces2-j-src/org/apache/xerces/impl/xs/ElementPSVImpl.java
new file mode 100644
index 0000000..6673bbc
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xs/ElementPSVImpl.java
@@ -0,0 +1,340 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xs;
+
+import org.apache.xerces.impl.dv.ValidatedInfo;
+import org.apache.xerces.impl.xs.util.StringListImpl;
+import org.apache.xerces.xs.ElementPSVI;
+import org.apache.xerces.xs.ItemPSVI;
+import org.apache.xerces.xs.ShortList;
+import org.apache.xerces.xs.StringList;
+import org.apache.xerces.xs.XSElementDeclaration;
+import org.apache.xerces.xs.XSModel;
+import org.apache.xerces.xs.XSNotationDeclaration;
+import org.apache.xerces.xs.XSSimpleTypeDefinition;
+import org.apache.xerces.xs.XSTypeDefinition;
+import org.apache.xerces.xs.XSValue;
+
+/**
+ * Element PSV infoset augmentations implementation.
+ * The following information will be available at the startElement call:
+ * name, namespace, type, notation, validation context
+ *
+ * The following information will be available at the endElement call:
+ * nil, specified, normalized value, member type, validity, error codes,
+ * default
+ *
+ * @xerces.internal
+ *
+ * @author Elena Litani IBM
+ * @version $Id$
+ */
+public class ElementPSVImpl implements ElementPSVI {
+
+ /** element declaration */
+ protected XSElementDeclaration fDeclaration = null;
+
+ /** type of element, could be xsi:type */
+ protected XSTypeDefinition fTypeDecl = null;
+
+ /** true if clause 3.2 of Element Locally Valid (Element) (3.3.4)
+ * is satisfied, otherwise false
+ */
+ protected boolean fNil = false;
+
+ /** true if the element value was provided by the schema; false otherwise.
+ */
+ protected boolean fSpecified = false;
+
+ /** Schema value */
+ protected ValidatedInfo fValue = new ValidatedInfo();
+
+ /** http://www.w3.org/TR/xmlschema-1/#e-notation*/
+ protected XSNotationDeclaration fNotation = null;
+
+ /** validation attempted: none, partial, full */
+ protected short fValidationAttempted = ElementPSVI.VALIDATION_NONE;
+
+ /** validity: valid, invalid, unknown */
+ protected short fValidity = ElementPSVI.VALIDITY_NOTKNOWN;
+
+ /** error codes and error messages */
+ protected String[] fErrors = null;
+
+ /** validation context: could be QName or XPath expression*/
+ protected String fValidationContext = null;
+
+ /** deferred XSModel **/
+ protected SchemaGrammar[] fGrammars = null;
+
+ /** the schema information property */
+ protected XSModel fSchemaInformation = null;
+
+ /** true if this object is immutable **/
+ protected boolean fIsConstant;
+
+ public ElementPSVImpl() {}
+
+ public ElementPSVImpl(boolean isConstant, ElementPSVI elementPSVI) {
+ fDeclaration = elementPSVI.getElementDeclaration();
+ fTypeDecl = elementPSVI.getTypeDefinition();
+ fNil = elementPSVI.getNil();
+ fSpecified = elementPSVI.getIsSchemaSpecified();
+ fValue.copyFrom(elementPSVI.getSchemaValue());
+ fNotation = elementPSVI.getNotation();
+ fValidationAttempted = elementPSVI.getValidationAttempted();
+ fValidity = elementPSVI.getValidity();
+ fValidationContext = elementPSVI.getValidationContext();
+ if (elementPSVI instanceof ElementPSVImpl) {
+ final ElementPSVImpl elementPSVIImpl = (ElementPSVImpl) elementPSVI;
+ fErrors = (elementPSVIImpl.fErrors != null) ?
+ (String[]) elementPSVIImpl.fErrors.clone() : null;
+ elementPSVIImpl.copySchemaInformationTo(this);
+ }
+ else {
+ final StringList errorCodes = elementPSVI.getErrorCodes();
+ final int length = errorCodes.getLength();
+ if (length > 0) {
+ final StringList errorMessages = elementPSVI.getErrorMessages();
+ final String[] errors = new String[length << 1];
+ for (int i = 0, j = 0; i < length; ++i) {
+ errors[j++] = errorCodes.item(i);
+ errors[j++] = errorMessages.item(i);
+ }
+ fErrors = errors;
+ }
+ fSchemaInformation = elementPSVI.getSchemaInformation();
+ }
+ fIsConstant = isConstant;
+ }
+
+ //
+ // ElementPSVI methods
+ //
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#constant()
+ */
+ public ItemPSVI constant() {
+ if (isConstant()) {
+ return this;
+ }
+ return new ElementPSVImpl(true, this);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#isConstant()
+ */
+ public boolean isConstant() {
+ return fIsConstant;
+ }
+
+ /**
+ * [schema default]
+ *
+ * @return The canonical lexical representation of the declaration's {value constraint} value.
+ * @see XML Schema Part 1: Structures [schema normalized value]
+ * @return the normalized value of this item after validation
+ */
+ public String getSchemaNormalizedValue() {
+ return fValue.getNormalizedValue();
+ }
+
+ /**
+ * [schema specified]
+ * @see XML Schema Part 1: Structures [schema specified]
+ * @return true - value was specified in schema, false - value comes from the infoset
+ */
+ public boolean getIsSchemaSpecified() {
+ return fSpecified;
+ }
+
+ /**
+ * Determines the extent to which the document has been validated
+ *
+ * @return return the [validation attempted] property. The possible values are
+ * NO_VALIDATION, PARTIAL_VALIDATION and FULL_VALIDATION
+ */
+ public short getValidationAttempted() {
+ return fValidationAttempted;
+ }
+
+ /**
+ * Determine the validity of the node with respect
+ * to the validation being attempted
+ *
+ * @return return the [validity] property. Possible values are:
+ * UNKNOWN_VALIDITY, INVALID_VALIDITY, VALID_VALIDITY
+ */
+ public short getValidity() {
+ return fValidity;
+ }
+
+ /**
+ * A list of error codes generated from validation attempts.
+ * Need to find all the possible subclause reports that need reporting
+ *
+ * @return Array of error codes
+ */
+ public StringList getErrorCodes() {
+ if (fErrors == null || fErrors.length == 0) {
+ return StringListImpl.EMPTY_LIST;
+ }
+ return new PSVIErrorList(fErrors, true);
+ }
+
+ /**
+ * A list of error messages generated from the validation attempt or
+ * an empty StringList if no errors occurred during the
+ * validation attempt. The indices of error messages in this list are
+ * aligned with those in the [schema error code] list.
+ */
+ public StringList getErrorMessages() {
+ if (fErrors == null || fErrors.length == 0) {
+ return StringListImpl.EMPTY_LIST;
+ }
+ return new PSVIErrorList(fErrors, false);
+ }
+
+ // This is the only information we can provide in a pipeline.
+ public String getValidationContext() {
+ return fValidationContext;
+ }
+
+ /**
+ * [nil]
+ * @see XML Schema Part 1: Structures [notation]
+ * @return The notation declaration.
+ */
+ public XSNotationDeclaration getNotation() {
+ return fNotation;
+ }
+
+ /**
+ * An item isomorphic to the type definition used to validate this element.
+ *
+ * @return a type declaration
+ */
+ public XSTypeDefinition getTypeDefinition() {
+ return fTypeDecl;
+ }
+
+ /**
+ * If and only if that type definition is a simple type definition
+ * with {variety} union, or a complex type definition whose {content type}
+ * is a simple thype definition with {variety} union, then an item isomorphic
+ * to that member of the union's {member type definitions} which actually
+ * validated the element item's normalized value.
+ *
+ * @return a simple type declaration
+ */
+ public XSSimpleTypeDefinition getMemberTypeDefinition() {
+ return fValue.getMemberTypeDefinition();
+ }
+
+ /**
+ * An item isomorphic to the element declaration used to validate
+ * this element.
+ *
+ * @return an element declaration
+ */
+ public XSElementDeclaration getElementDeclaration() {
+ return fDeclaration;
+ }
+
+ /**
+ * [schema information]
+ * @see XML Schema Part 1: Structures [schema information]
+ * @return The schema information property if it's the validation root,
+ * null otherwise.
+ */
+ public synchronized XSModel getSchemaInformation() {
+ if (fSchemaInformation == null && fGrammars != null) {
+ fSchemaInformation = new XSModelImpl(fGrammars);
+ }
+ return fSchemaInformation;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getActualNormalizedValue()
+ */
+ public Object getActualNormalizedValue() {
+ return fValue.getActualValue();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getActualNormalizedValueType()
+ */
+ public short getActualNormalizedValueType() {
+ return fValue.getActualValueType();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getItemValueTypes()
+ */
+ public ShortList getItemValueTypes() {
+ return fValue.getListValueTypes();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xs.ItemPSVI#getSchemaValue()
+ */
+ public XSValue getSchemaValue() {
+ return fValue;
+ }
+
+ /**
+ * Reset() should be called in validator startElement(..) method.
+ */
+ public void reset() {
+ fDeclaration = null;
+ fTypeDecl = null;
+ fNil = false;
+ fSpecified = false;
+ fNotation = null;
+ fValidationAttempted = ElementPSVI.VALIDATION_NONE;
+ fValidity = ElementPSVI.VALIDITY_NOTKNOWN;
+ fErrors = null;
+ fValidationContext = null;
+ fValue.reset();
+ }
+
+ public void copySchemaInformationTo(ElementPSVImpl target) {
+ target.fGrammars = fGrammars;
+ target.fSchemaInformation = fSchemaInformation;
+ }
+}
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xs/FilePathToURI.java b/resources/xerces2-j-src/org/apache/xerces/impl/xs/FilePathToURI.java
new file mode 100644
index 0000000..76acb05
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xs/FilePathToURI.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xs;
+
+/**
+ * @xerces.internal
+ *
+ * @version $Id$
+ */
+final class FilePathToURI {
+
+ // which ASCII characters need to be escaped
+ private static boolean gNeedEscaping[] = new boolean[128];
+ // the first hex character if a character needs to be escaped
+ private static char gAfterEscaping1[] = new char[128];
+ // the second hex character if a character needs to be escaped
+ private static char gAfterEscaping2[] = new char[128];
+ private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+ // initialize the above 3 arrays
+ static {
+ for (int i = 0; i <= 0x1f; i++) {
+ gNeedEscaping[i] = true;
+ gAfterEscaping1[i] = gHexChs[i >> 4];
+ gAfterEscaping2[i] = gHexChs[i & 0xf];
+ }
+ gNeedEscaping[0x7f] = true;
+ gAfterEscaping1[0x7f] = '7';
+ gAfterEscaping2[0x7f] = 'F';
+ char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}',
+ '|', '\\', '^', '~', '[', ']', '`'};
+ int len = escChs.length;
+ char ch;
+ for (int i = 0; i < len; i++) {
+ ch = escChs[i];
+ gNeedEscaping[ch] = true;
+ gAfterEscaping1[ch] = gHexChs[ch >> 4];
+ gAfterEscaping2[ch] = gHexChs[ch & 0xf];
+ }
+ }
+
+ private FilePathToURI() {}
+
+ // To escape a file path to a URI, by using %HH to represent
+ // special ASCII characters: 0x00~0x1F, 0x7F, ' ', '<', '>', '#', '%'
+ // and '"' and non-ASCII characters (whose value >= 128).
+ public static String filepath2URI(String path){
+ // return null if path is null.
+ if (path == null)
+ return null;
+
+ char separator = java.io.File.separatorChar;
+ path = path.replace(separator, '/');
+
+ int len = path.length(), ch;
+ StringBuffer buffer = new StringBuffer(len*3);
+ buffer.append("file://");
+ // change C:/blah to /C:/blah
+ if (len >= 2 && path.charAt(1) == ':') {
+ ch = Character.toUpperCase(path.charAt(0));
+ if (ch >= 'A' && ch <= 'Z') {
+ buffer.append('/');
+ }
+ }
+
+ // for each character in the path
+ int i = 0;
+ for (; i < len; i++) {
+ ch = path.charAt(i);
+ // if it's not an ASCII character, break here, and use UTF-8 encoding
+ if (ch >= 128)
+ break;
+ if (gNeedEscaping[ch]) {
+ buffer.append('%');
+ buffer.append(gAfterEscaping1[ch]);
+ buffer.append(gAfterEscaping2[ch]);
+ // record the fact that it's escaped
+ }
+ else {
+ buffer.append((char)ch);
+ }
+ }
+
+ // we saw some non-ascii character
+ if (i < len) {
+ // get UTF-8 bytes for the remaining sub-string
+ byte[] bytes = null;
+ byte b;
+ try {
+ bytes = path.substring(i).getBytes("UTF-8");
+ } catch (java.io.UnsupportedEncodingException e) {
+ // should never happen
+ return path;
+ }
+ len = bytes.length;
+
+ // for each byte
+ for (i = 0; i < len; i++) {
+ b = bytes[i];
+ // for non-ascii character: make it positive, then escape
+ if (b < 0) {
+ ch = b + 256;
+ buffer.append('%');
+ buffer.append(gHexChs[ch >> 4]);
+ buffer.append(gHexChs[ch & 0xf]);
+ }
+ else if (gNeedEscaping[b]) {
+ buffer.append('%');
+ buffer.append(gAfterEscaping1[b]);
+ buffer.append(gAfterEscaping2[b]);
+ }
+ else {
+ buffer.append((char)b);
+ }
+ }
+ }
+
+ return buffer.toString();
+ }
+
+} //FilePathToURI
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xs/PSVIErrorList.java b/resources/xerces2-j-src/org/apache/xerces/impl/xs/PSVIErrorList.java
new file mode 100644
index 0000000..36e2615
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xs/PSVIErrorList.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xs;
+
+import java.util.AbstractList;
+
+import org.apache.xerces.xs.StringList;
+
+/**
+ * StringList implementation for schema error codes and error messages.
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ *
+ * @version $Id$
+ */
+final class PSVIErrorList extends AbstractList implements StringList {
+
+ private final String[] fArray;
+ private final int fLength;
+ private final int fOffset;
+
+ public PSVIErrorList(String[] array, boolean even) {
+ fArray = array;
+ fLength = (fArray.length >> 1);
+ fOffset = even ? 0 : 1;
+ }
+
+ public boolean contains(String item) {
+ if (item == null) {
+ for (int i = 0; i < fLength; ++i) {
+ if (fArray[(i << 1) + fOffset] == null) {
+ return true;
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < fLength; ++i) {
+ if (item.equals(fArray[(i << 1) + fOffset])) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public String item(int index) {
+ if (index < 0 || index >= fLength) {
+ return null;
+ }
+ return fArray[(index << 1) + fOffset];
+ }
+
+ /*
+ * List methods
+ */
+
+ public Object get(int index) {
+ if (index >= 0 && index < fLength) {
+ return fArray[(index << 1) + fOffset];
+ }
+ throw new IndexOutOfBoundsException("Index: " + index);
+ }
+
+ public int size() {
+ return getLength();
+ }
+
+} // class PSVIErrorList
diff --git a/resources/xerces2-j-src/org/apache/xerces/impl/xs/SchemaGrammar.java b/resources/xerces2-j-src/org/apache/xerces/impl/xs/SchemaGrammar.java
new file mode 100644
index 0000000..ae88c28
--- /dev/null
+++ b/resources/xerces2-j-src/org/apache/xerces/impl/xs/SchemaGrammar.java
@@ -0,0 +1,1689 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.xerces.impl.xs;
+
+import java.lang.ref.SoftReference;
+import java.util.Vector;
+
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.impl.dv.SchemaDVFactory;
+import org.apache.xerces.impl.dv.ValidatedInfo;
+import org.apache.xerces.impl.dv.XSSimpleType;
+import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl;
+import org.apache.xerces.impl.xs.identity.IdentityConstraint;
+import org.apache.xerces.impl.xs.util.ObjectListImpl;
+import org.apache.xerces.impl.xs.util.SimpleLocator;
+import org.apache.xerces.impl.xs.util.StringListImpl;
+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.parsers.DOMParser;
+import org.apache.xerces.parsers.SAXParser;
+import org.apache.xerces.parsers.XML11Configuration;
+import org.apache.xerces.util.SymbolHash;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.grammars.XMLGrammarDescription;
+import org.apache.xerces.xni.grammars.XSGrammar;
+import org.apache.xerces.xs.StringList;
+import org.apache.xerces.xs.XSAnnotation;
+import org.apache.xerces.xs.XSAttributeDeclaration;
+import org.apache.xerces.xs.XSAttributeGroupDefinition;
+import org.apache.xerces.xs.XSConstants;
+import org.apache.xerces.xs.XSElementDeclaration;
+import org.apache.xerces.xs.XSIDCDefinition;
+import org.apache.xerces.xs.XSModel;
+import org.apache.xerces.xs.XSModelGroupDefinition;
+import org.apache.xerces.xs.XSNamedMap;
+import org.apache.xerces.xs.XSNamespaceItem;
+import org.apache.xerces.xs.XSNotationDeclaration;
+import org.apache.xerces.xs.XSObjectList;
+import org.apache.xerces.xs.XSTypeDefinition;
+import org.apache.xerces.xs.XSWildcard;
+import org.apache.xerces.xs.datatypes.ObjectList;
+import org.xml.sax.SAXException;
+
+/**
+ * This class is to hold all schema component declaration that are declared
+ * within one namespace.
+ *
+ * The Grammar class this class extends contains what little
+ * commonality there is between XML Schema and DTD grammars. It's
+ * useful to distinguish grammar objects from other kinds of object
+ * when they exist in pools or caches.
+ *
+ * @xerces.internal
+ *
+ * @author Sandy Gao, IBM
+ * @author Elena Litani, IBM
+ *
+ * @version $Id$
+ */
+
+public class SchemaGrammar implements XSGrammar, XSNamespaceItem {
+
+ // the target namespace of grammar
+ String fTargetNamespace;
+
+ // global decls: map from decl name to decl object
+ SymbolHash fGlobalAttrDecls;
+ SymbolHash fGlobalAttrGrpDecls;
+ SymbolHash fGlobalElemDecls;
+ SymbolHash fGlobalGroupDecls;
+ SymbolHash fGlobalNotationDecls;
+ SymbolHash fGlobalIDConstraintDecls;
+ SymbolHash fGlobalTypeDecls;
+
+ // extended global decls: map from schema location + decl name to decl object
+ // key is location,name
+ SymbolHash fGlobalAttrDeclsExt;
+ SymbolHash fGlobalAttrGrpDeclsExt;
+ SymbolHash fGlobalElemDeclsExt;
+ SymbolHash fGlobalGroupDeclsExt;
+ SymbolHash fGlobalNotationDeclsExt;
+ SymbolHash fGlobalIDConstraintDeclsExt;
+ SymbolHash fGlobalTypeDeclsExt;
+
+ // A global map of all global element declarations - used for substitution group computation
+ // (handy when sharing components by reference, since we might end up with duplicate components
+ // that are not added to either of the global element declarations above)
+ SymbolHash fAllGlobalElemDecls;
+
+ // the XMLGrammarDescription member
+ XSDDescription fGrammarDescription = null;
+
+ // annotations associated with the "root" schema of this targetNamespace
+ XSAnnotationImpl [] fAnnotations = null;
+
+ // number of annotations declared
+ int fNumAnnotations;
+
+ // symbol table for constructing parsers (annotation support)
+ private SymbolTable fSymbolTable = null;
+ // parsers for annotation support
+ private SoftReference fSAXParser = null;
+ private SoftReference fDOMParser = null;
+
+ // is this grammar immutable? (fully constructed and not changeable)
+ private boolean fIsImmutable = false;
+
+ //
+ // Constructors
+ //
+
+ // needed to make BuiltinSchemaGrammar work.
+ protected SchemaGrammar() {}
+
+ /**
+ * Default constructor.
+ *
+ * @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,
+ SymbolTable symbolTable) {
+ fTargetNamespace = targetNamespace;
+ fGrammarDescription = grammarDesc;
+ fSymbolTable = symbolTable;
+
+ // REVISIT: the initial sizes being chosen for each SymbolHash
+ // may not be ideal and could still be tuned. They were chosen
+ // somewhat arbitrarily to reduce the initial footprint of
+ // SymbolHash buckets from 1,515 to 177 (about 12% of the
+ // default size).
+ fGlobalAttrDecls = new SymbolHash(12);
+ fGlobalAttrGrpDecls = new SymbolHash(5);
+ fGlobalElemDecls = new SymbolHash(25);
+ fGlobalGroupDecls = new SymbolHash(5);
+ fGlobalNotationDecls = new SymbolHash(1);
+ fGlobalIDConstraintDecls = new SymbolHash(3);
+
+ // Extended tables
+ fGlobalAttrDeclsExt = new SymbolHash(12);
+ fGlobalAttrGrpDeclsExt = new SymbolHash(5);
+ fGlobalElemDeclsExt = new SymbolHash(25);
+ fGlobalGroupDeclsExt = new SymbolHash(5);
+ fGlobalNotationDeclsExt = new SymbolHash(1);
+ fGlobalIDConstraintDeclsExt = new SymbolHash(3);
+ fGlobalTypeDeclsExt = new SymbolHash(25);
+
+ // All global elements table
+ fAllGlobalElemDecls = new SymbolHash(25);
+
+ // if we are parsing S4S, put built-in types in first
+ // they might get overwritten by the types from S4S, but that's
+ // considered what the application wants to do.
+ if (fTargetNamespace == SchemaSymbols.URI_SCHEMAFORSCHEMA) {
+ fGlobalTypeDecls = SG_SchemaNS.fGlobalTypeDecls.makeClone();
+ }
+ else {
+ fGlobalTypeDecls = new SymbolHash(25);
+ }
+ } // (String, XSDDescription)
+
+ // Clone an existing schema grammar
+ public SchemaGrammar(SchemaGrammar grammar) {
+ fTargetNamespace = grammar.fTargetNamespace;
+ fGrammarDescription = grammar.fGrammarDescription.makeClone();
+ //fGrammarDescription.fContextType |= XSDDescription.CONTEXT_COLLISION; // REVISIT
+ fSymbolTable = grammar.fSymbolTable; // REVISIT
+
+ fGlobalAttrDecls = grammar.fGlobalAttrDecls.makeClone();
+ fGlobalAttrGrpDecls = grammar.fGlobalAttrGrpDecls.makeClone();
+ fGlobalElemDecls = grammar.fGlobalElemDecls.makeClone();
+ fGlobalGroupDecls = grammar.fGlobalGroupDecls.makeClone();
+ fGlobalNotationDecls = grammar.fGlobalNotationDecls.makeClone();
+ fGlobalIDConstraintDecls = grammar.fGlobalIDConstraintDecls.makeClone();
+ fGlobalTypeDecls = grammar.fGlobalTypeDecls.makeClone();
+
+ // Extended tables
+ fGlobalAttrDeclsExt = grammar.fGlobalAttrDeclsExt.makeClone();
+ fGlobalAttrGrpDeclsExt = grammar.fGlobalAttrGrpDeclsExt.makeClone();
+ fGlobalElemDeclsExt = grammar.fGlobalElemDeclsExt.makeClone();
+ fGlobalGroupDeclsExt = grammar.fGlobalGroupDeclsExt.makeClone();
+ fGlobalNotationDeclsExt = grammar.fGlobalNotationDeclsExt.makeClone();
+ fGlobalIDConstraintDeclsExt = grammar.fGlobalIDConstraintDeclsExt.makeClone();
+ fGlobalTypeDeclsExt = grammar.fGlobalTypeDeclsExt.makeClone();
+
+ // All global elements table
+ fAllGlobalElemDecls = grammar.fAllGlobalElemDecls.makeClone();
+
+ // Annotations associated with the "root" schema of this targetNamespace
+ fNumAnnotations = grammar.fNumAnnotations;
+ if (fNumAnnotations > 0) {
+ fAnnotations = new XSAnnotationImpl[grammar.fAnnotations.length];
+ System.arraycopy(grammar.fAnnotations, 0, fAnnotations, 0, fNumAnnotations);
+ }
+
+ // All substitution group information declared in this namespace
+ fSubGroupCount = grammar.fSubGroupCount;
+ if (fSubGroupCount > 0) {
+ fSubGroups = new XSElementDecl[grammar.fSubGroups.length];
+ System.arraycopy(grammar.fSubGroups, 0, fSubGroups, 0, fSubGroupCount);
+ }
+
+ // Array to store complex type decls for constraint checking
+ fCTCount = grammar.fCTCount;
+ if (fCTCount > 0) {
+ fComplexTypeDecls = new XSComplexTypeDecl[grammar.fComplexTypeDecls.length];
+ fCTLocators = new SimpleLocator[grammar.fCTLocators.length];
+ System.arraycopy(grammar.fComplexTypeDecls, 0, fComplexTypeDecls, 0, fCTCount);
+ System.arraycopy(grammar.fCTLocators, 0, fCTLocators, 0, fCTCount);
+ }
+
+ // Groups being redefined by restriction
+ fRGCount = grammar.fRGCount;
+ if (fRGCount > 0) {
+ fRedefinedGroupDecls = new XSGroupDecl[grammar.fRedefinedGroupDecls.length];
+ fRGLocators = new SimpleLocator[grammar.fRGLocators.length];
+ System.arraycopy(grammar.fRedefinedGroupDecls, 0, fRedefinedGroupDecls, 0, fRGCount);
+ System.arraycopy(grammar.fRGLocators, 0, fRGLocators, 0, fRGCount/2);
+ }
+
+ // List of imported grammars
+ if (grammar.fImported != null) {
+ fImported = new Vector();
+ for (int i=0; i(String, XSDDescription)
+
+ // number of built-in XSTypes we need to create for base and full
+ // datatype set
+ private static final int BASICSET_COUNT = 29;
+ private static final int FULLSET_COUNT = 46;
+
+ private static final int GRAMMAR_XS = 1;
+ private static final int GRAMMAR_XSI = 2;
+
+ // this class makes sure the static, built-in schema grammars
+ // are immutable.
+ public static class BuiltinSchemaGrammar extends SchemaGrammar {
+
+ private static final String EXTENDED_SCHEMA_FACTORY_CLASS = "org.apache.xerces.impl.dv.xs.ExtendedSchemaDVFactoryImpl";
+
+ /**
+ * Special constructor to create the grammars for the schema namespaces
+ *
+ * @param grammar
+ */
+ public BuiltinSchemaGrammar(int grammar, short schemaVersion) {
+ SchemaDVFactory schemaFactory;
+ if (schemaVersion == Constants.SCHEMA_VERSION_1_0) {
+ schemaFactory = SchemaDVFactory.getInstance();
+ }
+ else {
+ schemaFactory = SchemaDVFactory.getInstance(EXTENDED_SCHEMA_FACTORY_CLASS);
+ }
+
+ if (grammar == GRAMMAR_XS) {
+ // target namespace
+ fTargetNamespace = SchemaSymbols.URI_SCHEMAFORSCHEMA;
+
+ // grammar description
+ fGrammarDescription = new XSDDescription();
+ fGrammarDescription.fContextType = XSDDescription.CONTEXT_PREPARSE;
+ fGrammarDescription.setNamespace(SchemaSymbols.URI_SCHEMAFORSCHEMA);
+
+ // no global decls other than types
+ fGlobalAttrDecls = new SymbolHash(1);
+ fGlobalAttrGrpDecls = new SymbolHash(1);
+ fGlobalElemDecls = new SymbolHash(1);
+ fGlobalGroupDecls = new SymbolHash(1);
+ fGlobalNotationDecls = new SymbolHash(1);
+ fGlobalIDConstraintDecls = new SymbolHash(1);
+
+ // no extended global decls
+ fGlobalAttrDeclsExt = new SymbolHash(1);
+ fGlobalAttrGrpDeclsExt = new SymbolHash(1);
+ fGlobalElemDeclsExt = new SymbolHash(1);
+ fGlobalGroupDeclsExt = new SymbolHash(1);
+ fGlobalNotationDeclsExt = new SymbolHash(1);
+ fGlobalIDConstraintDeclsExt = new SymbolHash(1);
+ fGlobalTypeDeclsExt = new SymbolHash(1);
+
+ // all global element decls table
+ fAllGlobalElemDecls = new SymbolHash(1);
+
+ // get all built-in types
+ fGlobalTypeDecls = schemaFactory.getBuiltInTypes();
+
+ // assign the built-in schema grammar as the XSNamespaceItem
+ // for each of the built-in simple type definitions.
+ int length = fGlobalTypeDecls.getLength();
+ XSTypeDefinition [] typeDefinitions = new XSTypeDefinition[length];
+ fGlobalTypeDecls.getValues(typeDefinitions, 0);
+ for (int i = 0; i < length; ++i) {
+ XSTypeDefinition xtd = typeDefinitions[i];
+ if (xtd instanceof XSSimpleTypeDecl) {
+ ((XSSimpleTypeDecl) xtd).setNamespaceItem(this);
+ }
+ }
+
+ // add anyType
+ fGlobalTypeDecls.put(fAnyType.getName(), fAnyType);
+ }
+ else if (grammar == GRAMMAR_XSI) {
+ // target namespace
+ fTargetNamespace = SchemaSymbols.URI_XSI;
+ // grammar description
+ fGrammarDescription = new XSDDescription();
+ fGrammarDescription.fContextType = XSDDescription.CONTEXT_PREPARSE;
+ fGrammarDescription.setNamespace(SchemaSymbols.URI_XSI);
+
+ // no global decls other than attributes
+ fGlobalAttrGrpDecls = new SymbolHash(1);
+ fGlobalElemDecls = new SymbolHash(1);
+ fGlobalGroupDecls = new SymbolHash(1);
+ fGlobalNotationDecls = new SymbolHash(1);
+ fGlobalIDConstraintDecls = new SymbolHash(1);
+ fGlobalTypeDecls = new SymbolHash(1);
+
+ // no extended global decls
+ fGlobalAttrDeclsExt = new SymbolHash(1);
+ fGlobalAttrGrpDeclsExt = new SymbolHash(1);
+ fGlobalElemDeclsExt = new SymbolHash(1);
+ fGlobalGroupDeclsExt = new SymbolHash(1);
+ fGlobalNotationDeclsExt = new SymbolHash(1);
+ fGlobalIDConstraintDeclsExt = new SymbolHash(1);
+ fGlobalTypeDeclsExt = new SymbolHash(1);
+
+ // no all global element decls
+ fAllGlobalElemDecls = new SymbolHash(1);
+
+ // 4 attributes, so initialize the size as 4*2 = 8
+ fGlobalAttrDecls = new SymbolHash(8);
+ String name = null;
+ String tns = null;
+ XSSimpleType type = null;
+ short scope = XSConstants.SCOPE_GLOBAL;
+
+ // xsi:type
+ name = SchemaSymbols.XSI_TYPE;
+ tns = SchemaSymbols.URI_XSI;
+ type = schemaFactory.getBuiltInType(SchemaSymbols.ATTVAL_QNAME);
+ fGlobalAttrDecls.put(name, new BuiltinAttrDecl(name, tns, type, scope));
+
+ // xsi:nil
+ name = SchemaSymbols.XSI_NIL;
+ tns = SchemaSymbols.URI_XSI;
+ type = schemaFactory.getBuiltInType(SchemaSymbols.ATTVAL_BOOLEAN);
+ fGlobalAttrDecls.put(name, new BuiltinAttrDecl(name, tns, type, scope));
+
+ XSSimpleType anyURI = schemaFactory.getBuiltInType(SchemaSymbols.ATTVAL_ANYURI);
+
+ // xsi:schemaLocation
+ name = SchemaSymbols.XSI_SCHEMALOCATION;
+ tns = SchemaSymbols.URI_XSI;
+ type = schemaFactory.createTypeList("#AnonType_schemaLocation", SchemaSymbols.URI_XSI, (short)0, anyURI, null);
+ if (type instanceof XSSimpleTypeDecl) {
+ ((XSSimpleTypeDecl)type).setAnonymous(true);
+ }
+ fGlobalAttrDecls.put(name, new BuiltinAttrDecl(name, tns, type, scope));
+
+ // xsi:noNamespaceSchemaLocation
+ name = SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION;
+ tns = SchemaSymbols.URI_XSI;
+ type = anyURI;
+ fGlobalAttrDecls.put(name, new BuiltinAttrDecl(name, tns, type, scope));
+ }
+ } // (int)
+
+ // return the XMLGrammarDescription corresponding to this
+ // object
+ public XMLGrammarDescription getGrammarDescription() {
+ return fGrammarDescription.makeClone();
+ } // getGrammarDescription(): XMLGrammarDescription
+
+ // override these methods solely so that these
+ // objects cannot be modified once they're created.
+ public void setImportedGrammars(Vector importedGrammars) {
+ // ignore
+ }
+ public void addGlobalAttributeDecl(XSAttributeDecl decl) {
+ // ignore
+ }
+ public void addGlobalAttributeDecl(XSAttributeDecl decl, String location) {
+ // ignore
+ }
+ public void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl) {
+ // ignore
+ }
+ public void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl, String location) {
+ // ignore
+ }
+ public void addGlobalElementDecl(XSElementDecl decl) {
+ // ignore
+ }
+ public void addGlobalElementDecl(XSElementDecl decl, String location) {
+ // ignore
+ }
+ public void addGlobalElementDeclAll(XSElementDecl decl) {
+ // ignore
+ }
+ public void addGlobalGroupDecl(XSGroupDecl decl) {
+ // ignore
+ }
+ public void addGlobalGroupDecl(XSGroupDecl decl, String location) {
+ // ignore
+ }
+ public void addGlobalNotationDecl(XSNotationDecl decl) {
+ // ignore
+ }
+ public void addGlobalNotationDecl(XSNotationDecl decl, String location) {
+ // ignore
+ }
+ public void addGlobalTypeDecl(XSTypeDefinition decl) {
+ // ignore
+ }
+ public void addGlobalTypeDecl(XSTypeDefinition decl, String location) {
+ // ignore
+ }
+ public void addGlobalComplexTypeDecl(XSComplexTypeDecl decl) {
+ // ignore
+ }
+ public void addGlobalComplexTypeDecl(XSComplexTypeDecl decl, String location) {
+ // ignore
+ }
+ public void addGlobalSimpleTypeDecl(XSSimpleType decl) {
+ // ignore
+ }
+ public void addGlobalSimpleTypeDecl(XSSimpleType decl, String location) {
+ // ignore
+ }
+ public void addComplexTypeDecl(XSComplexTypeDecl decl, SimpleLocator locator) {
+ // ignore
+ }
+ public void addRedefinedGroupDecl(XSGroupDecl derived, XSGroupDecl base, SimpleLocator locator) {
+ // ignore
+ }
+ public synchronized void addDocument(Object document, String location) {
+ // ignore
+ }
+
+ // annotation support
+ synchronized DOMParser getDOMParser() {
+ return null;
+ }
+ synchronized SAXParser getSAXParser() {
+ return null;
+ }
+ }
+
+ /**
+ * A partial schema for schemas for validating annotations.
+ *
+ * @xerces.internal
+ *
+ * @author Michael Glavassevich, IBM
+ */
+ public static final class Schema4Annotations extends SchemaGrammar {
+
+ /**
+ * Singleton instance.
+ */
+ public static final Schema4Annotations INSTANCE = new Schema4Annotations();
+
+ /**
+ * Special constructor to create a schema
+ * capable of validating annotations.
+ */
+ private Schema4Annotations() {
+
+ // target namespace
+ fTargetNamespace = SchemaSymbols.URI_SCHEMAFORSCHEMA;
+
+ // grammar description
+ fGrammarDescription = new XSDDescription();
+ fGrammarDescription.fContextType = XSDDescription.CONTEXT_PREPARSE;
+ fGrammarDescription.setNamespace(SchemaSymbols.URI_SCHEMAFORSCHEMA);
+
+ // no global decls other than types and
+ // element declarations for , and .
+ fGlobalAttrDecls = new SymbolHash(1);
+ fGlobalAttrGrpDecls = new SymbolHash(1);
+ fGlobalElemDecls = new SymbolHash(6);
+ fGlobalGroupDecls = new SymbolHash(1);
+ fGlobalNotationDecls = new SymbolHash(1);
+ fGlobalIDConstraintDecls = new SymbolHash(1);
+
+ // no extended global decls
+ fGlobalAttrDeclsExt = new SymbolHash(1);
+ fGlobalAttrGrpDeclsExt = new SymbolHash(1);
+ fGlobalElemDeclsExt = new SymbolHash(6);
+ fGlobalGroupDeclsExt = new SymbolHash(1);
+ fGlobalNotationDeclsExt = new SymbolHash(1);
+ fGlobalIDConstraintDeclsExt = new SymbolHash(1);
+ fGlobalTypeDeclsExt = new SymbolHash(1);
+
+ // all global element declarations
+ fAllGlobalElemDecls = new SymbolHash(6);
+
+ // get all built-in types
+ fGlobalTypeDecls = SG_SchemaNS.fGlobalTypeDecls;
+
+ // create element declarations for , and
+ XSElementDecl annotationDecl = createAnnotationElementDecl(SchemaSymbols.ELT_ANNOTATION);
+ XSElementDecl documentationDecl = createAnnotationElementDecl(SchemaSymbols.ELT_DOCUMENTATION);
+ XSElementDecl appinfoDecl = createAnnotationElementDecl(SchemaSymbols.ELT_APPINFO);
+
+ // add global element declarations
+ fGlobalElemDecls.put(annotationDecl.fName, annotationDecl);
+ fGlobalElemDecls.put(documentationDecl.fName, documentationDecl);
+ fGlobalElemDecls.put(appinfoDecl.fName, appinfoDecl);
+
+ fGlobalElemDeclsExt.put(","+annotationDecl.fName, annotationDecl);
+ fGlobalElemDeclsExt.put(","+documentationDecl.fName, documentationDecl);
+ fGlobalElemDeclsExt.put(","+appinfoDecl.fName, appinfoDecl);
+
+ fAllGlobalElemDecls.put(annotationDecl, annotationDecl);
+ fAllGlobalElemDecls.put(documentationDecl, documentationDecl);
+ fAllGlobalElemDecls.put(appinfoDecl, appinfoDecl);
+
+ // create complex type declarations for , and
+ XSComplexTypeDecl annotationType = new XSComplexTypeDecl();
+ XSComplexTypeDecl documentationType = new XSComplexTypeDecl();
+ XSComplexTypeDecl appinfoType = new XSComplexTypeDecl();
+
+ // set the types on their element declarations
+ annotationDecl.fType = annotationType;
+ documentationDecl.fType = documentationType;
+ appinfoDecl.fType = appinfoType;
+
+ // create attribute groups for , and
+ XSAttributeGroupDecl annotationAttrs = new XSAttributeGroupDecl();
+ XSAttributeGroupDecl documentationAttrs = new XSAttributeGroupDecl();
+ XSAttributeGroupDecl appinfoAttrs = new XSAttributeGroupDecl();
+
+ // fill in attribute groups
+ {
+ // create and fill attribute uses for , and
+ XSAttributeUseImpl annotationIDAttr = new XSAttributeUseImpl();
+ annotationIDAttr.fAttrDecl = new XSAttributeDecl();
+ annotationIDAttr.fAttrDecl.setValues(SchemaSymbols.ATT_ID, null, (XSSimpleType) fGlobalTypeDecls.get(SchemaSymbols.ATTVAL_ID),
+ XSConstants.VC_NONE, XSConstants.SCOPE_LOCAL, null, annotationType, null);
+ annotationIDAttr.fUse = SchemaSymbols.USE_OPTIONAL;
+ annotationIDAttr.fConstraintType = XSConstants.VC_NONE;
+
+ XSAttributeUseImpl documentationSourceAttr = new XSAttributeUseImpl();
+ documentationSourceAttr.fAttrDecl = new XSAttributeDecl();
+ documentationSourceAttr.fAttrDecl.setValues(SchemaSymbols.ATT_SOURCE, null, (XSSimpleType) fGlobalTypeDecls.get(SchemaSymbols.ATTVAL_ANYURI),
+ XSConstants.VC_NONE, XSConstants.SCOPE_LOCAL, null, documentationType, null);
+ documentationSourceAttr.fUse = SchemaSymbols.USE_OPTIONAL;
+ documentationSourceAttr.fConstraintType = XSConstants.VC_NONE;
+
+ XSAttributeUseImpl documentationLangAttr = new XSAttributeUseImpl();
+ documentationLangAttr.fAttrDecl = new XSAttributeDecl();
+ documentationLangAttr.fAttrDecl.setValues("lang".intern(), NamespaceContext.XML_URI, (XSSimpleType) fGlobalTypeDecls.get(SchemaSymbols.ATTVAL_LANGUAGE),
+ XSConstants.VC_NONE, XSConstants.SCOPE_LOCAL, null, documentationType, null);
+ documentationLangAttr.fUse = SchemaSymbols.USE_OPTIONAL;
+ documentationLangAttr.fConstraintType = XSConstants.VC_NONE;
+
+ XSAttributeUseImpl appinfoSourceAttr = new XSAttributeUseImpl();
+ appinfoSourceAttr.fAttrDecl = new XSAttributeDecl();
+ appinfoSourceAttr.fAttrDecl.setValues(SchemaSymbols.ATT_SOURCE, null, (XSSimpleType) fGlobalTypeDecls.get(SchemaSymbols.ATTVAL_ANYURI),
+ XSConstants.VC_NONE, XSConstants.SCOPE_LOCAL, null, appinfoType, null);
+ appinfoSourceAttr.fUse = SchemaSymbols.USE_OPTIONAL;
+ appinfoSourceAttr.fConstraintType = XSConstants.VC_NONE;
+
+ // create lax attribute wildcard for , and
+ XSWildcardDecl otherAttrs = new XSWildcardDecl();
+ otherAttrs.fNamespaceList = new String [] {fTargetNamespace, null};
+ otherAttrs.fType = XSWildcard.NSCONSTRAINT_NOT;
+ otherAttrs.fProcessContents = XSWildcard.PC_LAX;
+
+ // add attribute uses and wildcards to attribute groups for , and
+ annotationAttrs.addAttributeUse(annotationIDAttr);
+ annotationAttrs.fAttributeWC = otherAttrs;
+
+ documentationAttrs.addAttributeUse(documentationSourceAttr);
+ documentationAttrs.addAttributeUse(documentationLangAttr);
+ documentationAttrs.fAttributeWC = otherAttrs;
+
+ appinfoAttrs.addAttributeUse(appinfoSourceAttr);
+ appinfoAttrs.fAttributeWC = otherAttrs;
+ }
+
+ // create particles for
+ XSParticleDecl annotationParticle = createUnboundedModelGroupParticle();
+ {
+ XSModelGroupImpl annotationChoice = new XSModelGroupImpl();
+ annotationChoice.fCompositor = XSModelGroupImpl.MODELGROUP_CHOICE;
+ annotationChoice.fParticleCount = 2;
+ annotationChoice.fParticles = new XSParticleDecl[2];
+ annotationChoice.fParticles[0] = createChoiceElementParticle(appinfoDecl);
+ annotationChoice.fParticles[1] = createChoiceElementParticle(documentationDecl);
+ annotationParticle.fValue = annotationChoice;
+ }
+
+ // create wildcard particle for and |