Xalan3 specific additions and updates
git-svn-id: https://svn.apache.org/repos/asf/xalan/java/branches/xalan3@336637 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/org/apache/xml/dtm/DTM.java b/src/org/apache/xml/dtm/DTM.java
index 14446d1..27fd1ed 100644
--- a/src/org/apache/xml/dtm/DTM.java
+++ b/src/org/apache/xml/dtm/DTM.java
@@ -57,6 +57,7 @@
package org.apache.xml.dtm;
import org.apache.xml.utils.XMLString;
+import org.apache.xpath.objects.*;
import javax.xml.transform.SourceLocator;
@@ -192,9 +193,11 @@
public static final short NAMESPACE_NODE = 13;
/**
- * The number of valid nodetypes.
+ * The number of valid nodetypes. REMEMBER TO UPDATE THIS if you add more
+ * node types.
*/
public static final short NTYPES = 14;
+
// ========= DTM Implementation Control Functions. ==============
// %TBD% RETIRED -- do via setFeature if needed. Remove from impls.
@@ -217,6 +220,7 @@
* @param value an <code>Object</code> value
*/
public void setProperty(String property, Object value);
+
// ========= Document Navigation Functions =========
@@ -999,6 +1003,75 @@
* to shutdown any subsystem activity that may of been assoiated with
* the active DTM Implementation.
*/
+ public void documentRelease();
+
+
+ /**
+ * EXPERIMENTAL XPath2 Support:
+ *
+ * Query schema type name of a given node.
+ *
+ * %REVIEW% Is this actually needed?
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return null if no type known, else returns the expanded-QName (namespace URI
+ * rather than prefix) of the type actually
+ * resolved in the instance document. Note that this may be derived from,
+ * rather than identical to, the type declared in the schema.
+ */
+ public String getSchemaTypeName(int nodeHandle);
+
+ /**
+ * EXPERIMENTAL XPath2 Support:
+ *
+ * Query schema type namespace of a given node.
+ *
+ * %REVIEW% Is this actually needed?
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return null if no type known, else returns the namespace URI
+ * of the type actually resolved in the instance document. This may
+ * be null if the default/unspecified namespace was used.
+ * Note that this may be derived from,
+ * rather than identical to, the type declared in the schema.
+ */
+ public String getSchemaTypeNamespace(int nodeHandle);
- public void documentRelease();
+ /** EXPERIMENTAL XPath2 Support: Query schema type localname of a given node.
+ *
+ * %REVIEW% Is this actually needed?
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return null if no type known, else returns the localname of the type
+ * resolved in the instance document. Note that this may be derived from,
+ * rather than identical to, the type declared in the schema.
+ */
+ public String getSchemaTypeLocalName(int nodeHandle);
+
+ /** EXPERIMENTAL XPath2 Support: Query whether node's type is derived from a specific type
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @param namespace String containing URI of namespace for the type we're intersted in
+ * @param localname String containing local name for the type we're intersted in
+ * @return true if node has a Schema Type which equals or is derived from
+ * the specified type. False if the node has no type or that type is not
+ * derived from the specified type.
+ */
+ public boolean isNodeSchemaType(int nodeHandle, String namespace, String localname);
+
+ /** EXPERIMENTAL XPath2 Support: Retrieve the typed value(s), based on the schema
+ * type.
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return XSequence object containing one or more values and their type
+ * information. If no typed value is available, returns an empty sequence.
+ * */
+ public DTMSequence getTypedValue(int nodeHandle);
+
+ /** Query which DTMManager this DTM is currently being handled by.
+ *
+ * @return a DTMManager, or null if this is a "stand-alone" DTM.
+ */
+ public DTMManager getManager();
+
}
diff --git a/src/org/apache/xml/dtm/DTMFilter.java b/src/org/apache/xml/dtm/DTMFilter.java
index 5efd4b8..e85ea45 100644
--- a/src/org/apache/xml/dtm/DTMFilter.java
+++ b/src/org/apache/xml/dtm/DTMFilter.java
@@ -175,6 +175,24 @@
* possibly, to create a DTM-specific field for these additional bits.
*/
public static final int SHOW_BYFUNCTION = 0x00010000;
+
+ /**
+ * Special bit for supporting "item" in ItemType..
+ * <p>
+ * %REVIEW% Might be safer to start from higher bits and work down,
+ * to leave room for the DOM to expand its set of constants... Or,
+ * possibly, to create a DTM-specific field for these additional bits.
+ */
+ public static final int SHOW_ITEM = 0x00020000;
+
+ /**
+ * Special bit for supporting "untyped" in ItemType..
+ * <p>
+ * %REVIEW% Might be safer to start from higher bits and work down,
+ * to leave room for the DOM to expand its set of constants... Or,
+ * possibly, to create a DTM-specific field for these additional bits.
+ */
+ public static final int SHOW_UNTYPED = 0x00040000;
/**
* Test whether a specified node is visible in the logical view of a
diff --git a/src/org/apache/xml/dtm/DTMIterator.java b/src/org/apache/xml/dtm/DTMIterator.java
index 68633c3..a02c1d9 100644
--- a/src/org/apache/xml/dtm/DTMIterator.java
+++ b/src/org/apache/xml/dtm/DTMIterator.java
@@ -256,16 +256,18 @@
//========= Random Access ==========
/**
- * If setShouldCacheNodes(true) is called, then nodes will
+ * If setShouldCache(true) is called, then nodes will
* be cached, enabling random access, and giving the ability to do
* sorts and the like. They are not cached by default.
*
- * %REVIEW% Shouldn't the other random-access methods throw an exception
- * if they're called on a DTMIterator with this flag set false?
+ * %REVIEW% Should random-access methods
+ * (specifically setCurrentPosition() and item())
+ * throw an exception if they're called on a DTMIterator
+ * with this flag set false?
*
* @param b true if the nodes should be cached.
*/
- public void setShouldCacheNodes(boolean b);
+ public void setShouldCache(boolean b);
/**
* Tells if this iterator can have nodes added to it or set via
diff --git a/src/org/apache/xml/dtm/DTMManager.java b/src/org/apache/xml/dtm/DTMManager.java
index f0033ca..4604af7 100644
--- a/src/org/apache/xml/dtm/DTMManager.java
+++ b/src/org/apache/xml/dtm/DTMManager.java
@@ -486,7 +486,7 @@
System.err.println("DTM: found " + serviceId);
}
- BufferedReader rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+ BufferedReader rd = new BufferedReader(new InputStreamReader(is,"UTF-8"));
foundFactory = rd.readLine();
diff --git a/src/org/apache/xml/dtm/DTMSequence.java b/src/org/apache/xml/dtm/DTMSequence.java
new file mode 100644
index 0000000..59f21ff
--- /dev/null
+++ b/src/org/apache/xml/dtm/DTMSequence.java
@@ -0,0 +1,131 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.xml.dtm;
+
+import java.util.Vector;
+
+
+// Xerces XNI post-Schema datatype support
+import org.apache.xerces.xni.psvi.ElementPSVI;
+import org.apache.xerces.xni.psvi.AttributePSVI;
+import org.apache.xerces.xni.psvi.ItemPSVI;
+import org.apache.xerces.impl.xs.ElementPSVImpl;
+import org.apache.xerces.impl.xs.AttributePSVImpl;
+import org.apache.xerces.impl.xs.XSTypeDecl;
+import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl;
+
+/** This interface provides an API representation for the XPath 2
+ * Data Model's "Sequences" -- which are the basic representation
+ * for typed values. Only built-in types, types derived from
+ * built-ins, and sets thereof are returned directly by the XPath2
+ * DM; complex schema-types must be accessed through the document tree.
+ *
+ * The interface also provides XSequence.EMPTY, an empty sequence,
+ * as a manefest constant.
+ * */
+public interface DTMSequence
+{
+ /** @return the number of members in this sequence. */
+ public int getLength();
+
+ /** Retrieve the value for this member of the sequence. Since values may be
+ * a heterogenous mix, and their type may not be known until they're examined,
+ * they're returned as Objects. This is storage-inefficient if the value(s)
+ * is/are builtins that map to Java primitives. Tough.
+ *
+ * @param index 0-based index into the sequence.
+ * @return the specified value
+ * @throws exception if index <0 or >=length
+ * */
+ public Object getValue(int index);
+
+ /** Retrieve the datatype namespace URI for this member of the sequence.
+ *
+ * @param index 0-based index into the sequence.
+ * @return the namespace for the specified value's type
+ * @throws exception if index <0 or >=length
+ * */
+ public String getTypeNS(int index);
+
+ /** Retrieve the datatype namespace URI for this member of the sequence.
+ *
+ * %REVIEW% Do we really need type --
+ * or can we just tell folks to do instanceOf on the Java value objects?
+ *
+ * @param index 0-based index into the sequence.
+ * @return the localname of the specified value's type
+ * @throws exception if index <0 or >=length
+ * */
+ public String getTypeLocalName(int index);
+
+ /** Ask whether this member's datatype equals or is derived from a specified
+ * schema NSURI/localname pair.
+ *
+ * @param index 0-based index into the sequence.
+ * @return true if the type is an instance of this schema datatype,
+ * false if it isn't.
+ * @throws exception if index <0 or >=length
+ * */
+ public boolean isSchemaType(int index, String namespace, String localname);
+
+
+ /** MANAFEST CONSTANT: An empty XSequence, which can be returned when no
+ * typed value exists.
+ * */
+ public static final DTMSequence EMPTY = new DTMSequenceEmpty();
+}
+
diff --git a/src/org/apache/xml/dtm/DTMSequenceEmpty.java b/src/org/apache/xml/dtm/DTMSequenceEmpty.java
new file mode 100644
index 0000000..63960fa
--- /dev/null
+++ b/src/org/apache/xml/dtm/DTMSequenceEmpty.java
@@ -0,0 +1,131 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.xml.dtm;
+
+/**
+ * The responsibility of enclosing_type is to .
+ *
+ * Created Jul 15, 2002
+ * @author sboag
+ */
+class DTMSequenceEmpty implements DTMSequence
+{
+ /** @return the number of members in this sequence. */
+ public int getLength()
+ {
+ return 0;
+ }
+
+ /** Retrieve the value for this member of the sequence. Since values may be
+ * a heterogenous mix, and their type may not be known until they're examined,
+ * they're returned as Objects. This is storage-inefficient if the value(s)
+ * is/are builtins that map to Java primitives. Tough.
+ *
+ * @param index 0-based index into the sequence.
+ * @return the specified value
+ * @throws exception if index <0 or >=length
+ * */
+ public Object getValue(int index)
+ {
+ throw new java.lang.ArrayIndexOutOfBoundsException();
+ }
+
+ /** Retrieve the datatype namespace URI for this member of the sequence.
+ *
+ * @param index 0-based index into the sequence.
+ * @return the namespace for the specified value's type
+ * @throws exception if index <0 or >=length
+ * */
+ public String getTypeNS(int index)
+ {
+ throw new java.lang.ArrayIndexOutOfBoundsException();
+ }
+
+ /** Retrieve the datatype namespace URI for this member of the sequence.
+ *
+ * %REVIEW% Do we really need type --
+ * or can we just tell folks to do instanceOf on the Java value objects?
+ *
+ * @param index 0-based index into the sequence.
+ * @return the localname of the specified value's type
+ * @throws exception if index <0 or >=length
+ * */
+ public String getTypeLocalName(int index)
+ {
+ throw new java.lang.ArrayIndexOutOfBoundsException();
+ }
+
+ /** Ask whether this member's datatype equals or is derived from a specified
+ * schema NSURI/localname pair.
+ *
+ * @param index 0-based index into the sequence.
+ * @return true if the type is an instance of this schema datatype,
+ * false if it isn't.
+ * @throws exception if index <0 or >=length
+ * */
+ public boolean isSchemaType(int index, String namespace, String localname)
+ {
+ throw new java.lang.ArrayIndexOutOfBoundsException();
+ }
+
+ /** %REVIEW% Format not yet firmly settled. Primarily for debugging purposes!
+ * */
+ public String toString()
+ {
+ return "EmptySequence[]";
+ }
+}
diff --git a/src/org/apache/xml/dtm/XType.java b/src/org/apache/xml/dtm/XType.java
new file mode 100644
index 0000000..f72224f
--- /dev/null
+++ b/src/org/apache/xml/dtm/XType.java
@@ -0,0 +1,342 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.xml.dtm;
+
+import java.net.URL;
+import java.util.Hashtable;
+
+import org.apache.xml.utils.QName;
+
+/**
+ * The responsibility of XType is to provide static information about
+ * types, like the ID and the name.
+ *
+ * Created Jul 16, 2002
+ * @author sboag
+ */
+public class XType
+{
+ // These values need to be what they are, at least for right now. -sb
+ // (This is because of the method resolver in the extension mechanism!)
+ public static final int ANYTYPE = 0;
+ public static final int BOOLEAN = 1;
+ public static final int DOUBLE = 2;
+ public static final int STRING = 3;
+ public static final int NODE = 4;
+ public static final int RTREEFRAG = 5;
+
+ // Callers should expect the actual values of these constants to
+ // changed... i.e. they should not rely on the value itself.
+ public static final int BASE64BINARY = 6;
+ public static final int HEXBINARY = 7;
+ public static final int FLOAT = 8;
+ public static final int DECIMAL = 9;
+ public static final int INTEGER = 10;
+ public static final int ANYURI = 11;
+ public static final int QNAME = 12;
+ public static final int NOTATION = 13;
+ public static final int DURATION = 14;
+ public static final int DATETIME = 15;
+ public static final int TIME = 16;
+ public static final int DATE = 17;
+ public static final int GYEARMONTH = 18;
+ public static final int GYEAR = 19;
+ public static final int GMONTHDAY = 20;
+ public static final int GDAY = 21;
+ public static final int GMONTH = 22;
+
+ public static final int YEARMONTHDURATION = 23;
+ public static final int DAYTIMEDURATION = 24;
+
+ public static final int ANYSIMPLETYPE = 25;
+ public static final int EMPTYSEQ = 26;
+
+ // Answer for a sequence when it hasn't iterated. -sb
+ public static final int SEQ = 27;
+
+
+ public static final int MAXTYPES = 27;
+
+ // This is probably primarily for diagnostic purposes.
+ private static final String[] m_names =
+ {
+ "AnyType", // ANYTYPE = 0;
+ "boolean", // BOOLEAN = 1;
+ "double", // DOUBLE = 2;
+ "string", // STRING = 3;
+ "NODE", // NODE = 4;
+ "RTreeRfrag", // RTREEFRAG = 5;
+ "base64Binary", // BASE64BINARY = 6;
+ "hexBinary", // HEXBINARY = 7;
+ "float", // FLOAT = 8;
+ "decimal", // DECIMAL = 9;
+ "integer", // INTEGER = 10;
+ "anyURI", // ANYURI = 11;
+ "QName", // QNAME = 12;
+ "NOTATION", // NOTATION = 13;
+ "duration", // DURATION = 14;
+ "dateTime", // DATETIME = 15;
+ "time", // TIME = 16;
+ "date", // DATE = 17;
+ "gYearMonth", // GYEARMONTH = 18;
+ "gYear", // GYEAR = 19;
+ "gMonthDay", // GMONTHDAY = 20;
+ "gDay", // GDAY = 21;
+ "gMonth", // GMONTH = 22;
+ "yearMonthDuration", // YEARMONTHDURATION = 23;
+ "dayTimeDuration", // DAYTIMEDURATION = 24;
+ "AnySimpleType", // ANYSIMPLETYPE = 25;
+ "EMPTY" // EMPTYSEQ = 26;
+ };
+
+ public static final int NOTHOMOGENOUS = 0xFFFFFFFF;
+
+ private static Hashtable m_nameToIDs;
+
+ static
+ {
+ m_nameToIDs = new Hashtable();
+ m_nameToIDs.put("string", new Integer(STRING));
+ m_nameToIDs.put("boolean", new Integer(BOOLEAN));
+ m_nameToIDs.put("decimal", new Integer(DECIMAL));
+ m_nameToIDs.put("integer", new Integer(INTEGER));
+ m_nameToIDs.put("float", new Integer(FLOAT));
+ m_nameToIDs.put("double", new Integer(DOUBLE));
+ m_nameToIDs.put("duration", new Integer(DURATION));
+ m_nameToIDs.put("dateTime", new Integer(DATETIME));
+ m_nameToIDs.put("time", new Integer(TIME));
+ m_nameToIDs.put("date", new Integer(DATE));
+ m_nameToIDs.put("gYearMonth", new Integer(GYEARMONTH));
+ m_nameToIDs.put("gYear", new Integer(GYEAR));
+ m_nameToIDs.put("gMonthDay", new Integer(GMONTHDAY));
+ m_nameToIDs.put("gDay", new Integer(GDAY));
+ m_nameToIDs.put("gMonth", new Integer(GMONTH));
+ m_nameToIDs.put("hexBinary", new Integer(HEXBINARY));
+ m_nameToIDs.put("base64Binary", new Integer(BASE64BINARY));
+ m_nameToIDs.put("anyURI", new Integer(ANYURI));
+ m_nameToIDs.put("QName", new Integer(QNAME));
+ m_nameToIDs.put("NOTATION", new Integer(NOTATION));
+ m_nameToIDs.put("yearMonthDuration", new Integer(YEARMONTHDURATION));
+ m_nameToIDs.put("dayTimeDuration", new Integer(DAYTIMEDURATION));
+ }
+
+ /** Manefest constant: Namespace of schema built-in datatypes.
+ * Provided here as a coding convenience.
+ * */
+ public static final String XMLSCHEMA_DATATYPE_NAMESPACE="http://www.w3.org/2001/XMLSchema-datatypes";
+
+ /** Manefest constant: Namespace of schema declarations.
+ * Provided here as a coding convenience.
+ * */
+ public static final String XMLSCHEMA_NAMESPACE="http://www.w3.org/2001/XMLSchema";
+
+ /**
+ * Get the type ID that maps to a local name, The namespace
+ * URI of "http://www.w3.org/2001/XMLSchema-datatypes" is assumed.
+ *
+ * @param localName The local name of a type.
+ * @return one of STRING, BOOLEAN, etc, or ANYTYPE if the string does
+ * not map to any name.
+ */
+ public static int getTypeFromLocalName(String localName)
+ {
+ Integer idObj = (Integer)m_nameToIDs.get(localName);
+ return (null != idObj) ? idObj.intValue() : ANYTYPE;
+ }
+
+ /**
+ * Get the type ID that maps to a qualified name, The namespace
+ * of which must be URI of "http://www.w3.org/2001/XMLSchema-datatypes".
+ *
+ * @param namespace of data type
+ * @param localName of data type
+ * @return one of STRING, BOOLEAN, etc, or ANYTYPE if the string does
+ * not map to any name.
+ */
+ public static int getTypeID(String namespace, String localName)
+ {
+ if(null == namespace
+ || (!namespace.equals(XMLSCHEMA_DATATYPE_NAMESPACE)
+ && !namespace.equals(XMLSCHEMA_NAMESPACE)))
+ return ANYTYPE; // Should be good enough to test for error.
+ Integer idObj = (Integer)m_nameToIDs.get(localName);
+ return (null != idObj) ? idObj.intValue() : ANYTYPE;
+ }
+
+ /**
+ * Get the type ID that maps to a qualified name, The namespace
+ * of which must be URI of "http://www.w3.org/2001/XMLSchema-datatypes".
+ * This should probably be moved into the DTM interface?
+ *
+ * @param nodeHandle A handle to a node.
+ * @return one of STRING, BOOLEAN, etc, or ANYTYPE if the string does
+ * not map to any name.
+ */
+ public static int getTypeID(DTM dtm, int nodeHandle)
+ {
+ String namespace = dtm.getSchemaTypeNamespace(nodeHandle);
+ String localName = dtm.getSchemaTypeLocalName(nodeHandle);
+ if(null == namespace
+ || (!namespace.equals(XMLSCHEMA_DATATYPE_NAMESPACE)
+ && !namespace.equals(XMLSCHEMA_NAMESPACE)))
+ return ANYTYPE; // Should be good enough to test for error.
+ Integer idObj = (Integer)m_nameToIDs.get(localName);
+ return (null != idObj) ? idObj.intValue() : ANYTYPE;
+ }
+
+
+
+ /**
+ * Get the type ID that maps to a qualified name, The namespace
+ * of which must be URI of "http://www.w3.org/2001/XMLSchema-datatypes".
+ *
+ * @param qname A qualifed name object.
+ * @return one of STRING, BOOLEAN, etc, or ANYTYPE if the string does
+ * not map to any name.
+ */
+ public static int getTypeFromQName(QName qname)
+ {
+ String namespace = qname.getNamespaceURI();
+ if(null == namespace
+ || (!namespace.equals(XMLSCHEMA_DATATYPE_NAMESPACE)
+ && !namespace.equals(XMLSCHEMA_NAMESPACE)))
+ return ANYTYPE; // Should be good enough to test for error.
+ Integer idObj = (Integer)m_nameToIDs.get(qname.getLocalName());
+ return (null != idObj) ? idObj.intValue() : ANYTYPE;
+ }
+
+
+ /**
+ * Returns the nameToIDs table.
+ * @return Hashtable that contains Strings as the key, and Integers as
+ * the value.
+ */
+ public static Hashtable getNameToIDs()
+ {
+ return m_nameToIDs;
+ }
+
+ /**
+ * Get the type ID that maps to a local name, The namespace
+ * URI of "http://www.w3.org/2001/XMLSchema-datatypes" is assumed.
+ *
+ * @param id one of EMPTYSEQ, NODE, STRING, BOOLEAN, etc.
+ * @throws IndexOutOfBoundsException if id >= 22, or id < 0.
+ */
+ public static String getLocalNameFromType(int id)
+ {
+ return m_names[id];
+ }
+
+
+ /**
+ * Returns the names table, primarily for diagnostic purposes.
+ * @return String[]
+ */
+ public static String[] getNames()
+ {
+ return m_names;
+ }
+
+ /**
+ * This method does it's best to infer the type name from a
+ * java object.
+ * @param obj
+ * @return String
+ */
+ public static String inferLocalNameFromJavaObject(Object obj)
+ {
+ // public static final int STRING = 4;
+ // public static final int BOOLEAN = 5;
+ // public static final int BASE64BINARY = 6;
+ // public static final int HEXBINARY = 7;
+ // public static final int FLOAT = 8;
+ // public static final int DECIMAL = 9;
+ // public static final int INTEGER = 10;
+ // public static final int DOUBLE = 11;
+ // public static final int ANYURI = 12;
+ // public static final int QNAME = 13;
+ // public static final int NOTATION = 14;
+ // public static final int DURATION = 15;
+ // public static final int DATETIME = 16;
+ // public static final int TIME = 17;
+ // public static final int DATE = 18;
+ // public static final int GYEARMONTH = 19;
+ // public static final int GYEAR = 20;
+ // public static final int GMONTHDAY = 21;
+ // public static final int GDAY = 22;
+ // public static final int GMONTH = 23;
+ if(obj instanceof String)
+ return getLocalNameFromType(STRING);
+ else if(obj instanceof Boolean)
+ return getLocalNameFromType(BOOLEAN);
+ else if(obj instanceof Float)
+ return getLocalNameFromType(FLOAT);
+ else if(obj instanceof Double)
+ return getLocalNameFromType(DOUBLE);
+ else if(obj instanceof Integer)
+ return getLocalNameFromType(INTEGER);
+ else if(obj instanceof URL)
+ return getLocalNameFromType(ANYURI);
+ else if(obj instanceof QName)
+ return getLocalNameFromType(QNAME);
+ // TBD: all the rest.
+ else
+ return "unknown";
+ }
+
+}
diff --git a/src/org/apache/xml/dtm/XTypeConverter.java b/src/org/apache/xml/dtm/XTypeConverter.java
new file mode 100644
index 0000000..2ca2d30
--- /dev/null
+++ b/src/org/apache/xml/dtm/XTypeConverter.java
@@ -0,0 +1,252 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.xml.dtm;
+
+import java.util.Date;
+
+import org.apache.xerces.util.URI;
+import org.apache.xml.utils.QName;
+import org.apache.xml.utils.XMLString;
+
+/**
+ * This interface defines a type that can convert to the given type.
+ *
+ * Created Jul 18, 2002
+ * @author sboag
+ */
+public interface XTypeConverter
+{
+ // public static final int ANYTYPE = 2;
+ // public static final int ANYSIMPLETYPE = 3;
+
+ /**
+ * Return a java object that's closest to the representation
+ * that should be handed to an extension.
+ *
+ * @return The object that this class wraps
+ */
+ public Object object();
+
+ // public static final int STRING = 4;
+ /**
+ * Cast result object to a string.
+ *
+ * @return The object as a string
+ */
+ public String str();
+
+ /**
+ * Cast result object to an XString.
+ *
+ * @return The object as a string
+ */
+ public XMLString xstr();
+
+ // public static final int BOOLEAN = 5;
+ /**
+ * Cast result object to a float.
+ *
+ * @return float value.
+ */
+ public boolean bool();
+
+ // public static final int BASE64BINARY = 6;
+ /**
+ * Cast result object to a float.
+ *
+ * @return float value.
+ */
+ public Object base64Binary();
+
+ // public static final int HEXBINARY = 7;
+ /**
+ * Cast result object to a float.
+ *
+ * @return float value.
+ */
+ public Object hexBinary();
+
+ // public static final int FLOAT = 8;
+ /**
+ * Cast result object to a float.
+ *
+ * @return float value.
+ */
+ public float floatCast();
+
+
+ // public static final int DECIMAL = 9;
+ /**
+ * Cast result object to a double (for lack of something better. -sb)
+ *
+ * @return 0.0
+ */
+ public double decimal();
+
+ // public static final int INTEGER = 10;
+ /**
+ * Cast result object to a integer.
+ *
+ * @return integer value.
+ */
+ public int integer();
+
+ // public static final int DOUBLE = 11;
+ /**
+ * Cast result object to a double.
+ *
+ * @return double value.
+ */
+ public double doubleCast();
+
+ // public static final int ANYURI = 12;
+ /**
+ * Cast result object to a double.
+ *
+ * @return URI object
+ */
+ public URI anyuri();
+
+ // public static final int QNAME = 13;
+ /**
+ * Cast result object to a double.
+ *
+ * @return QName object.
+ */
+ public QName qname();
+
+ // public static final int NOTATION = 14;
+ /**
+ * Cast result object to a String that representa a NOTATION.
+ * TBD: I think this needs to be a special object!
+ *
+ * @return String object
+ */
+ public String notation(); // not sure what to do with this!
+
+ // public static final int DURATION = 15;
+ /**
+ * Cast result object to a duration.
+ *
+ * @return Duration object
+ */
+ public Object duration(); // Use myriam's Duration
+
+ // public static final int DATETIME = 16;
+ /**
+ * Cast result object to a duration.
+ *
+ * @return Duration object
+ */
+ public Date datetime(); // Use myriam's
+
+ // public static final int TIME = 17;
+ /**
+ * Cast result object to a duration.
+ *
+ * @return Duration object
+ */
+ public Object time(); // Use myriam's
+
+ // public static final int DATE = 18;
+ /**
+ * Cast result object to a duration.
+ *
+ * @return Duration object
+ */
+ public Date date(); // Use myriam's
+
+ // public static final int GYEARMONTH = 19;
+ /**
+ * Cast result object to a duration.
+ *
+ * @return Duration object
+ */
+ public Object gYearMonth(); // Use myriam's
+
+ // public static final int GYEAR = 20;
+ /**
+ * Cast result object to a duration.
+ *
+ * @return Duration object
+ */
+ public Object gYear(); // Use myriam's
+
+ // public static final int GMONTHDAY = 21;
+ /**
+ * Cast result object to a duration.
+ *
+ * @return Duration object
+ */
+ public Object gMonthDay(); // Use myriam's
+
+ // public static final int GDAY = 22;
+ /**
+ * Cast result object to a duration.
+ *
+ * @return Duration object
+ */
+ public Object gDay(); // Use myriam's
+
+ // public static final int GMONTH = 23;
+ /**
+ * Cast result object to a duration.
+ *
+ * @return Duration object
+ */
+ public Object gMonth(); // Use myriam's
+}
diff --git a/src/org/apache/xml/dtm/ref/DTMDefaultBase.java b/src/org/apache/xml/dtm/ref/DTMDefaultBase.java
index 222eb57..1c345fb 100644
--- a/src/org/apache/xml/dtm/ref/DTMDefaultBase.java
+++ b/src/org/apache/xml/dtm/ref/DTMDefaultBase.java
@@ -56,33 +56,28 @@
*/
package org.apache.xml.dtm.ref;
-import org.apache.xml.dtm.*;
-import org.apache.xml.utils.SuballocatedIntVector;
-import org.apache.xml.utils.SuballocatedByteVector;
-import org.apache.xml.utils.IntStack;
-import org.apache.xml.utils.BoolStack;
-import org.apache.xml.utils.StringBufferPool;
-import org.apache.xml.utils.FastStringBuffer;
-import org.apache.xml.utils.TreeWalker;
-import org.apache.xml.utils.QName;
-import org.apache.xml.utils.XMLCharacterRecognizer;
-
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
import java.util.Vector;
-import org.xml.sax.ContentHandler;
-
-import org.apache.xml.utils.NodeVector;
-
import javax.xml.transform.Source;
-import org.apache.xml.utils.XMLString;
-import org.apache.xml.utils.XMLStringFactory;
-
import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
-
-import java.io.*; // for dumpDTM
-
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMAxisTraverser;
+import org.apache.xml.dtm.DTMException;
+import org.apache.xml.dtm.DTMManager;
+import org.apache.xml.dtm.DTMSequence;
+import org.apache.xml.dtm.DTMWSFilter;
+import org.apache.xml.utils.BoolStack;
+import org.apache.xml.utils.SuballocatedIntVector;
+import org.apache.xml.utils.XMLString;
+import org.apache.xml.utils.XMLStringFactory;
+import org.apache.xpath.objects.XSequence;
/**
* The <code>DTMDefaultBase</code> class serves as a helper base for DTMs.
* It sets up structures for navigation and type, while leaving data
@@ -460,7 +455,7 @@
if (NULL != info)
return m_expandedNameTable.getType(info);
else
- return NULL;
+ return (short)NULL;
}
/**
@@ -820,7 +815,7 @@
case DTM.NOTATION_NODE :
typestring = "NOTATION";
break;
- case DTM.NULL :
+ case (short)DTM.NULL:
typestring = "null";
break;
case DTM.PROCESSING_INSTRUCTION_NODE :
@@ -1401,7 +1396,7 @@
*/
public int getDocument()
{
- return m_dtmIdent.elementAt(0); // makeNodeHandle(0)
+ return m_dtmIdent.elementAt(0);
}
/**
@@ -1439,6 +1434,20 @@
}
/**
+ * Given a node identifier, find the owning document node. Unlike the DOM,
+ * this considers the owningDocument of a Document to be itself. Note that
+ * in shared DTMs this may not be zero.
+ *
+ * @param nodeId the id of the node.
+ * @return int Node identifier of owning document, or the nodeId if it is
+ * a Document.
+ */
+ protected int _documentRoot(int nodeIdentifier)
+ {
+ return 0;
+ }
+
+ /**
* Get the string-value of a node as a String object
* (see http://www.w3.org/TR/xpath#data-model
* for the definition of a node's string-value).
@@ -2128,8 +2137,6 @@
/** Query which DTMManager this DTM is currently being handled by.
*
- * %REVEW% Should this become part of the base DTM API?
- *
* @return a DTMManager, or null if this is a "stand-alone" DTM.
*/
public DTMManager getManager()
@@ -2148,4 +2155,73 @@
if(m_mgr==null) return null;
return m_dtmIdent;
}
+
+
+ /**
+ * EXPERIMENTAL XPath2 Support:
+ *
+ * Query schema type name of a given node.
+ *
+ * %REVIEW% Is this actually needed?
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return null if no type known, else returns the expanded-QName (namespace URI
+ * rather than prefix) of the type actually
+ * resolved in the instance document. Note that this may be derived from,
+ * rather than identical to, the type declared in the schema.
+ */
+ public String getSchemaTypeName(int nodeHandle)
+ { return null; }
+
+ /**
+ * EXPERIMENTAL XPath2 Support:
+ *
+ * Query schema type namespace of a given node.
+ *
+ * %REVIEW% Is this actually needed?
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return null if no type known, else returns the namespace URI
+ * of the type actually resolved in the instance document. This may
+ * be null if the default/unspecified namespace was used.
+ * Note that this may be derived from,
+ * rather than identical to, the type declared in the schema.
+ */
+ public String getSchemaTypeNamespace(int nodeHandle)
+ { return null; }
+
+ /** EXPERIMENTAL XPath2 Support: Query schema type localname of a given node.
+ *
+ * %REVIEW% Is this actually needed?
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return null if no type known, else returns the localname of the type
+ * resolved in the instance document. Note that this may be derived from,
+ * rather than identical to, the type declared in the schema.
+ */
+ public String getSchemaTypeLocalName(int nodeHandle)
+ { return null; }
+
+ /** EXPERIMENTAL XPath2 Support: Query whether node's type is derived from a specific type
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @param namespace String containing URI of namespace for the type we're intersted in
+ * @param localname String containing local name for the type we're intersted in
+ * @return true if node has a Schema Type which equals or is derived from
+ * the specified type. False if the node has no type or that type is not
+ * derived from the specified type.
+ */
+ public boolean isNodeSchemaType(int nodeHandle, String namespace, String localname)
+ { return false; }
+
+ /** EXPERIMENTAL XPath2 Support: Retrieve the typed value(s), based on the schema
+ * type.
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return XSequence object containing one or more values and their type
+ * information. If no typed value is available, returns an empty sequence.
+ * */
+ public DTMSequence getTypedValue(int nodeHandle)
+ {return DTMSequence.EMPTY;}
+
}
diff --git a/src/org/apache/xml/dtm/ref/DTMDefaultBaseIterators.java b/src/org/apache/xml/dtm/ref/DTMDefaultBaseIterators.java
index 304a023..b266f78 100644
--- a/src/org/apache/xml/dtm/ref/DTMDefaultBaseIterators.java
+++ b/src/org/apache/xml/dtm/ref/DTMDefaultBaseIterators.java
@@ -1491,6 +1491,8 @@
else
_startNode = getParent(node);
+ _currentNode = getDocumentRoot(node);
+
node = _startNode;
while (node != END)
{
@@ -1499,10 +1501,6 @@
}
m_ancestorsPos = m_ancestors.size()-1;
- _currentNode = (m_ancestorsPos>=0)
- ? m_ancestors.elementAt(m_ancestorsPos)
- : DTM.NULL;
-
return resetPosition();
}
@@ -1518,11 +1516,10 @@
public DTMAxisIterator reset()
{
+ _currentNode = getDocumentRoot(_startNode);
+
m_ancestorsPos = m_ancestors.size()-1;
- _currentNode = (m_ancestorsPos>=0) ? m_ancestors.elementAt(m_ancestorsPos)
- : DTM.NULL;
-
return resetPosition();
}
@@ -1536,10 +1533,11 @@
int next = _currentNode;
- int pos = --m_ancestorsPos;
-
- _currentNode = (pos >= 0) ? m_ancestors.elementAt(m_ancestorsPos)
- : DTM.NULL;
+ int pos = m_ancestorsPos--;
+ if(pos < 0)
+ _currentNode = DTM.NULL;
+ else
+ _currentNode = m_ancestors.elementAt(pos);
return returnNode(next);
}
diff --git a/src/org/apache/xml/dtm/ref/DTMDefaultBaseTraversers.java b/src/org/apache/xml/dtm/ref/DTMDefaultBaseTraversers.java
index 61b3de9..071003d 100644
--- a/src/org/apache/xml/dtm/ref/DTMDefaultBaseTraversers.java
+++ b/src/org/apache/xml/dtm/ref/DTMDefaultBaseTraversers.java
@@ -195,9 +195,8 @@
}
if (null == traverser)
- throw new DTMException(XSLMessages.createMessage(XSLTErrorResources.ER_AXIS_TRAVERSER_NOT_SUPPORTED, new Object[]{Axis.names[axis]}));
- // "Axis traverser not supported: "
- // + Axis.names[axis]);
+ throw new DTMException("Axis traverser not supported: "
+ + Axis.names[axis]);
m_traversers[axis] = traverser;
@@ -1257,7 +1256,8 @@
// compute in ID space
int subtreeRootIdent = makeNodeIdentity(context);
- for (current = makeNodeIdentity(current) - 1; current >= 0; current--)
+ int doc=_documentRoot(subtreeRootIdent);
+ for (current = makeNodeIdentity(current) - 1; current >= doc; current--)
{
short type = _type(current);
@@ -1286,7 +1286,8 @@
// Compute in ID space
int subtreeRootIdent = makeNodeIdentity(context);
- for (current = makeNodeIdentity(current) - 1; current >= 0; current--)
+ int doc=_documentRoot(subtreeRootIdent);
+ for (current = makeNodeIdentity(current) - 1; current >= doc; current--)
{
int exptype = m_exptype.elementAt(current);
@@ -1321,7 +1322,8 @@
// Compute in ID space
int subtreeRootIdent = makeNodeIdentity(context );
- for (current = makeNodeIdentity(current) - 1; current >= 0; current--)
+ int doc=_documentRoot(subtreeRootIdent);
+ for (current = makeNodeIdentity(current) - 1; current >= doc; current--)
{
short type = _type(current);
@@ -1349,7 +1351,8 @@
// Compute in ID space
int subtreeRootIdent = makeNodeIdentity(context);
- for (current = makeNodeIdentity(current) - 1; current >= 0; current--)
+ int doc=_documentRoot(subtreeRootIdent);
+ for (current = makeNodeIdentity(current) - 1; current >= doc; current--)
{
int exptype = m_exptype.elementAt(current);
@@ -1486,7 +1489,7 @@
*/
public int first(int context)
{
- return getDocument();
+ return getDocumentRoot(context);
}
/**
@@ -1499,7 +1502,7 @@
*/
public int first(int context, int expandedTypeID)
{
- return (getExpandedTypeID(getDocument()) == expandedTypeID)
+ return (getExpandedTypeID(getDocumentRoot(context)) == expandedTypeID)
? context : next(context, context, expandedTypeID);
}
@@ -1619,8 +1622,7 @@
*/
protected int getSubtreeRoot(int handle)
{
- // %REVIEW% Shouldn't this always be 0?
- return makeNodeIdentity(getDocument());
+ return _documentRoot(makeNodeIdentity(handle));
}
/**
@@ -1632,7 +1634,7 @@
*/
public int first(int context)
{
- return getDocument();
+ return getDocumentRoot(context);
}
/**
@@ -1653,7 +1655,7 @@
{
if (isIndexed(expandedTypeID))
{
- int identity = 0;
+ int identity = _documentRoot(makeNodeIdentity(context));
int firstPotential = getFirstPotential(identity);
return makeNodeHandle(getNextIndexed(identity, firstPotential, expandedTypeID));
@@ -1681,7 +1683,7 @@
*/
protected int getFirstPotential(int identity)
{
- return _firstch(0);
+ return _firstch(_documentRoot(identity));
}
/**
@@ -1691,7 +1693,7 @@
*/
protected int getSubtreeRoot(int handle)
{
- return 0;
+ return _documentRoot(makeNodeIdentity(handle));
}
/**
@@ -1703,7 +1705,7 @@
*/
public int first(int context)
{
- return makeNodeHandle(_firstch(0));
+ return makeNodeHandle(_firstch(_documentRoot(makeNodeIdentity(context))));
}
/**
@@ -1724,13 +1726,13 @@
{
if (isIndexed(expandedTypeID))
{
- int identity = 0;
+ int identity = _documentRoot(makeNodeIdentity(context));
int firstPotential = getFirstPotential(identity);
return makeNodeHandle(getNextIndexed(identity, firstPotential, expandedTypeID));
}
- int root = getDocument();
+ int root = getDocumentRoot(context);
return next(root, root, expandedTypeID);
}
diff --git a/src/org/apache/xml/dtm/ref/DTMDocumentImpl.java b/src/org/apache/xml/dtm/ref/DTMDocumentImpl.java
index 6a8ec80..30c7c88 100644
--- a/src/org/apache/xml/dtm/ref/DTMDocumentImpl.java
+++ b/src/org/apache/xml/dtm/ref/DTMDocumentImpl.java
@@ -56,23 +56,21 @@
*/
package org.apache.xml.dtm.ref;
-import org.apache.xml.dtm.*;
-import java.util.Hashtable;
-//import java.util.Stack;
-import java.util.Vector;
-
import javax.xml.transform.SourceLocator;
-import org.apache.xml.dtm.ref.ChunkedIntArray;
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMAxisIterator;
+import org.apache.xml.dtm.DTMAxisTraverser;
+import org.apache.xml.dtm.DTMManager;
+import org.apache.xml.dtm.DTMSequence;
+import org.apache.xml.dtm.DTMWSFilter;
import org.apache.xml.utils.FastStringBuffer;
-
-import org.xml.sax.ContentHandler;
-import org.xml.sax.Locator;
-import org.xml.sax.Attributes;
-import org.xml.sax.ext.LexicalHandler;
-
import org.apache.xml.utils.XMLString;
import org.apache.xml.utils.XMLStringFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.ext.LexicalHandler;
/**
* This is the implementation of the DTM document interface. It receives
@@ -148,6 +146,8 @@
* @see setIncrementalSAXSource
*/
private IncrementalSAXSource m_incrSAXSource=null;
+
+ DTMManager m_manager;
// ========= DTM data structure declarations. ==============
@@ -196,11 +196,15 @@
* DTMManager's responsibility to assign a unique number to each
* document.
*/
- public DTMDocumentImpl(DTMManager mgr, int documentNumber,
- DTMWSFilter whiteSpaceFilter,
- XMLStringFactory xstringfactory){
- initDocument(documentNumber); // clear nodes and document handle
- m_xsf = xstringfactory;
+ public DTMDocumentImpl(
+ DTMManager mgr,
+ int documentNumber,
+ DTMWSFilter whiteSpaceFilter,
+ XMLStringFactory xstringfactory)
+ {
+ m_manager = mgr;
+ initDocument(documentNumber); // clear nodes and document handle
+ m_xsf = xstringfactory;
}
/** Bind a IncrementalSAXSource to this DTM. If we discover we need nodes
@@ -2445,5 +2449,79 @@
{
}
+ /**
+ * EXPERIMENTAL XPath2 Support:
+ *
+ * Query schema type name of a given node.
+ *
+ * %REVIEW% Is this actually needed?
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return null if no type known, else returns the expanded-QName (namespace URI
+ * rather than prefix) of the type actually
+ * resolved in the instance document. Note that this may be derived from,
+ * rather than identical to, the type declared in the schema.
+ */
+ public String getSchemaTypeName(int nodeHandle)
+ { return null; }
+
+ /**
+ * EXPERIMENTAL XPath2 Support:
+ *
+ * Query schema type namespace of a given node.
+ *
+ * %REVIEW% Is this actually needed?
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return null if no type known, else returns the namespace URI
+ * of the type actually resolved in the instance document. This may
+ * be null if the default/unspecified namespace was used.
+ * Note that this may be derived from,
+ * rather than identical to, the type declared in the schema.
+ */
+ public String getSchemaTypeNamespace(int nodeHandle)
+ { return null; }
+
+ /** EXPERIMENTAL XPath2 Support: Query schema type localname of a given node.
+ *
+ * %REVIEW% Is this actually needed?
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return null if no type known, else returns the localname of the type
+ * resolved in the instance document. Note that this may be derived from,
+ * rather than identical to, the type declared in the schema.
+ */
+ public String getSchemaTypeLocalName(int nodeHandle)
+ { return null; }
+
+ /** EXPERIMENTAL XPath2 Support: Query whether node's type is derived from a specific type
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @param namespace String containing URI of namespace for the type we're intersted in
+ * @param localname String containing local name for the type we're intersted in
+ * @return true if node has a Schema Type which equals or is derived from
+ * the specified type. False if the node has no type or that type is not
+ * derived from the specified type.
+ */
+ public boolean isNodeSchemaType(int nodeHandle, String namespace, String localname)
+ { return false; }
+
+ /** EXPERIMENTAL XPath2 Support: Retrieve the typed value(s), based on the schema
+ * type.
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return XSequence object containing one or more values and their type
+ * information. If no typed value is available, returns an empty sequence.
+ * */
+ public DTMSequence getTypedValue(int nodeHandle)
+ {return DTMSequence.EMPTY;}
+
+ /**
+ * @see org.apache.xml.dtm.DTM#getManager()
+ */
+ public DTMManager getManager()
+ {
+ return m_manager;
+ }
}
diff --git a/src/org/apache/xml/dtm/ref/DTMManagerDefault.java b/src/org/apache/xml/dtm/ref/DTMManagerDefault.java
index 2d76162..26eebf4 100644
--- a/src/org/apache/xml/dtm/ref/DTMManagerDefault.java
+++ b/src/org/apache/xml/dtm/ref/DTMManagerDefault.java
@@ -73,12 +73,13 @@
import org.apache.xml.utils.SystemIDResolver;
import org.apache.xml.dtm.ref.dom2dtm.DOM2DTM;
import org.apache.xml.dtm.ref.sax2dtm.SAX2DTM;
-import org.apache.xml.dtm.ref.sax2dtm.SAX2RTFDTM;
+//import org.apache.xml.dtm.ref.sax2dtm.SAX2RTFDTM;
-/**************************************************************
+/**************************************************************/
// EXPERIMENTAL 3/22/02
import org.apache.xml.dtm.ref.xni2dtm.XNI2DTM;
-**************************************************************/
+import org.apache.xml.dtm.ref.xni2dtm.XNISource;
+/**************************************************************/
// W3C DOM
import org.w3c.dom.Document;
@@ -121,12 +122,10 @@
* */
public class DTMManagerDefault extends DTMManager
{
- //static final boolean JKESS_XNI_EXPERIMENT=true;
-
/** Set this to true if you want a dump of the DTM after creation. */
private static final boolean DUMPTREE = false;
- /** Set this to true if you want a basic diagnostics. */
+ /** Set this to true if you want basic diagnostics. */
private static final boolean DEBUG = false;
/**
@@ -275,7 +274,6 @@
DTMWSFilter whiteSpaceFilter,
boolean incremental, boolean doIndexing)
{
-
if(DEBUG && null != source)
System.out.println("Starting "+
(unique ? "UNIQUE" : "shared")+
@@ -286,243 +284,345 @@
int dtmPos = getFirstFreeDTMID();
int documentID = dtmPos << IDENT_DTM_NODE_BITS;
- if ((null != source) && source instanceof DOMSource)
+ if (source instanceof DOMSource)
{
+ // Simplest case: Wrap a DTM around an existing DOM.
+ //
+ // %REVIEW% May get more complicated if we start trying to match
+ // DOM2DTM implementations against specific DOM implementations,
+ // eg taking advantage of a particular DOM's hashability or
+ // userData hooks.
DOM2DTM dtm = new DOM2DTM(this, (DOMSource) source, documentID,
whiteSpaceFilter, xstringFactory, doIndexing);
+ addDTM(dtm, dtmPos, 0);
+ return dtm;
+ }
+
+ if(source==null)
+ {
+ // Set up a DTM which will accept a SAX input stream to be bound later.
+ // Note that XNI is _not_ currently an option in this case.
+ SAX2DTM dtm;
+
+ if(unique && !incremental && !doIndexing)
+ {
+ // Special case to support RTF construction into shared DTM.
+ // It should actually still work for other uses,
+ // but may be slightly deoptimized relative to the base
+ // to allow it to deal with carrying multiple documents.
+ //
+ // %REVIEW% This is a sloppy way to request this mode;
+ // we need to consider architectural improvements.
+ dtm = new SAX2DTM(this, source, documentID, whiteSpaceFilter,
+ xstringFactory, doIndexing, true);
+ if(DEBUG)
+ System.out.println("CREATING RTF DTM: "+dtm);
+ }
+ else // Create the basic SAX2DTM.
+ {
+ dtm = new SAX2DTM(this, source, documentID, whiteSpaceFilter,
+ xstringFactory, doIndexing);
+ }
addDTM(dtm, dtmPos, 0);
- // if (DUMPTREE)
- // {
- // dtm.dumpDTM();
- // }
-
+ // If the source is null, but they requested an incremental build,
+ // then we still want to set up the IncrementalSAXSource stuff
+ // so it can be bound later.
+ if (this.m_incremental && incremental)
+ {
+ IncrementalSAXSource coParser=new IncrementalSAXSource_Filter();
+ dtm.setIncrementalSAXSource(coParser);
+ }
+
return dtm;
}
- else
+
+ if (source instanceof XNISource)
{
- boolean isSAXSource = (null != source)
- ? (source instanceof SAXSource) : true;
- boolean isStreamSource = (null != source)
- ? (source instanceof StreamSource) : false;
+ XNISource xsrc=(XNISource)source;
+
+ XNI2DTM dtm = new XNI2DTM(this, source, documentID, whiteSpaceFilter,
+ xstringFactory, doIndexing);
+ addDTM(dtm, dtmPos, 0);
+
+ xsrc.setDocumentHandler(dtm);
+ xsrc.setErrorHandler(dtm);
+
+ // XNI's document scanner does support incremental.
+ // Would require yet another flavor of incremental-source to
+ // glue it to our APIs. For now, just run it to completion.
+ // MOVE THIS DOWN !!!!!
+ // %REVIEW%
+ try
+ {
+ xsrc.reset();
+ xsrc.scanDocument(true);
+ }
+ catch (RuntimeException re)
+ {
+ throw re;
+ }
+ catch (Exception e)
+ {
+ throw new org.apache.xml.utils.WrappedRuntimeException(e);
+ }
+
+ return dtm;
+ } // XNISource
- if (isSAXSource || isStreamSource)
+ if (source instanceof StreamSource)
+ {
+ // Try processing it as XNI first, to get PSVI information!
+
+ // %REVIEW% Arguably, we shouldn't go XNI (or at least not
+ // Schema-validated?) unless it's requested and/or XSLT2/XPath2
+ // are in use, since the schema processor is so expensive.
+ // Unfortunately, we don't have the XPathContext here to ask
+ // which version of the language is in use...
+
+ InputSource xmlSource = SAXSource.sourceToInputSource(source);
+ String urlOfSource = xmlSource.getSystemId();
+ if (null != urlOfSource)
{
- XMLReader reader;
- InputSource xmlSource;
-
- if (null == source)
+ try
{
- xmlSource = null;
- reader = null;
+ urlOfSource=SystemIDResolver.getAbsoluteURI(urlOfSource);
}
- else
+ catch (Exception e)
{
- reader = getXMLReader(source);
- xmlSource = SAXSource.sourceToInputSource(source);
-
- String urlOfSource = xmlSource.getSystemId();
-
- if (null != urlOfSource)
- {
- try
- {
- urlOfSource = SystemIDResolver.getAbsoluteURI(urlOfSource);
- }
- catch (Exception e)
- {
-
- // %REVIEW% Is there a better way to send a warning?
- System.err.println("Can not absolutize URL: " + urlOfSource);
- }
-
- xmlSource.setSystemId(urlOfSource);
- }
+ // %REVIEW% Is there a better way to send a warning?
+ System.err.println("Can not absolutize URL: " + urlOfSource);
}
-
- SAX2DTM dtm;
- if(source==null && unique && !incremental && !doIndexing)
- {
- // Special case to support RTF construction into shared DTM.
- // It should actually still work for other uses,
- // but may be slightly deoptimized relative to the base
- // to allow it to deal with carrying multiple documents.
- //
- // %REVIEW% This is a sloppy way to request this mode;
- // we need to consider architectural improvements.
- dtm = new SAX2RTFDTM(this, source, documentID, whiteSpaceFilter,
- xstringFactory, doIndexing);
- }
- /**************************************************************
- // EXPERIMENTAL 3/22/02
- else if(JKESS_XNI_EXPERIMENT && m_incremental)
- {
- dtm = new XNI2DTM(this, source, documentID, whiteSpaceFilter,
- xstringFactory, doIndexing);
- }
- **************************************************************/
- else // Create the basic SAX2DTM.
- {
- dtm = new SAX2DTM(this, source, documentID, whiteSpaceFilter,
- xstringFactory, doIndexing);
- }
-
- // Go ahead and add the DTM to the lookup table. This needs to be
- // done before any parsing occurs. Note offset 0, since we've just
- // created a new DTM.
+ xmlSource.setSystemId(urlOfSource);
+ } // urlOfSource fixup
+
+ // %REVIEW% Need a better test for whether Xerces2 is available
+ // This one involves creating a SAX reader, then discarding
+ // it in order to build a lower-level XNI reader. Wasteful.
+ XMLReader reader = getXMLReader(source);
+ if(reader.getClass().getName().equals("org.apache.xerces.parsers.SAXParser"))
+ {
+ DTM dtm = new XNI2DTM(this, source, documentID, whiteSpaceFilter,
+ xstringFactory, doIndexing);
addDTM(dtm, dtmPos, 0);
-
- boolean haveXercesParser =
- (null != reader)
- && (reader.getClass().getName().equals("org.apache.xerces.parsers.SAXParser") );
-
- if (haveXercesParser)
- incremental = true; // No matter what. %REVIEW%
-
- // If the reader is null, but they still requested an incremental build,
- // then we still want to set up the IncrementalSAXSource stuff.
- if (this.m_incremental && incremental /* || ((null == reader) && incremental) */)
{
- IncrementalSAXSource coParser=null;
+ // %REVIEW% Currently this creates a new instance of Xerces, since
+ // there's no way to access the XNI APIs of an existing SAXParser.
+ // This is wasteful since a reader as already created.
+ // Can we rationalize this flow? Can we get Xerces improved?
+ IncrementalSAXSource_Xerces coParser;
+ coParser=(IncrementalSAXSource_Xerces)IncrementalSAXSource_Xerces.createIncrementalSAXSource();
- if (haveXercesParser)
- {
- // IncrementalSAXSource_Xerces to avoid threading.
- try {
- coParser=org.apache.xml.dtm.ref.IncrementalSAXSource_Xerces.createIncrementalSAXSource();
- } catch( Exception ex ) {
- ex.printStackTrace();
- coParser=null;
- }
- }
-
- if( coParser==null ) {
- // Create a IncrementalSAXSource that will run on the secondary thread.
- if (null == reader)
- coParser = new IncrementalSAXSource_Filter();
- else
- {
- IncrementalSAXSource_Filter filter=new IncrementalSAXSource_Filter();
- filter.setXMLReader(reader);
- coParser=filter;
- }
-
- }
-
-
- /**************************************************************
- // EXPERIMENTAL 3/22/02
- if(JKESS_XNI_EXPERIMENT && m_incremental &
- dtm instanceof XNI2DTM &&
- coParser instanceof IncrementalSAXSource_Xerces)
- {
- org.apache.xerces.xni.parser.XMLPullParserConfiguration xpc=
- ((IncrementalSAXSource_Xerces)coParser).getXNIParserConfiguration();
- if(xpc!=null)
- // Bypass SAX; listen to the XNI stream
- ((XNI2DTM)dtm).setIncrementalXNISource(xpc);
- else
- // Listen to the SAX stream (will fail, diagnostically...)
- dtm.setIncrementalSAXSource(coParser);
- } else
- ***************************************************************/
+ // Bypass SAX; listen to the XNI stream
+ // %REVIEW% This shouldn't have a compile-time dependency on Xerces2!
+ // Can we fix it? (Change to Object?)
+ org.apache.xerces.xni.parser.XMLPullParserConfiguration xpc=
+ ((IncrementalSAXSource_Xerces)coParser).getXNIParserConfiguration();
+ ((XNI2DTM)dtm).setIncrementalXNISource(xpc);
- // Have the DTM set itself up as the IncrementalSAXSource's listener.
- dtm.setIncrementalSAXSource(coParser);
-
- if (null == xmlSource)
- {
-
- // Then the user will construct it themselves.
- return dtm;
- }
-
- if(null == reader.getErrorHandler())
- reader.setErrorHandler(dtm);
- reader.setDTDHandler(dtm);
-
try
{
-
- // Launch parsing coroutine. Launches a second thread,
- // if we're using IncrementalSAXSource.filter().
+ // Launch parsing coroutine.
coParser.startParse(xmlSource);
+
+ // %REVIEW% Kluge: Run nominal incremental setup in non-incremental
+ // mode. Simplifies this code, but it's a badly mixed metaphor.
+ if(!this.m_incremental)
+ coParser.deliverAllNodes();
}
catch (RuntimeException re)
{
-
- dtm.clearCoRoutine();
-
throw re;
}
catch (Exception e)
{
-
- dtm.clearCoRoutine();
-
throw new org.apache.xml.utils.WrappedRuntimeException(e);
}
- }
- else
+
+ return dtm;
+ } // if incremental
+
+ } // If Xerces2
+
+ // Fallback: Turn it into a SAX request. (We _could_ just let
+ // it fall through unchanged and put an OR in SAX case, as I do
+ // when disabling this block for debugging purposes... but
+ // I think making it explicit may be clearer.
+ source=new SAXSource(reader,xmlSource);
+ // FALL THROUGH to SAX processing
+ } // if streamsource
+
+
+ if ((source instanceof SAXSource)
+ // || (!JJK_ENABLE_XNI && source instanceof StreamSource) // debug fallback
+ )
+ {
+ XMLReader reader;
+ InputSource xmlSource;
+ SAX2DTM dtm;
+
+ reader = getXMLReader(source);
+ xmlSource = SAXSource.sourceToInputSource(source);
+
+ String urlOfSource = xmlSource.getSystemId();
+ if (null != urlOfSource)
+ {
+ try
{
+ urlOfSource=SystemIDResolver.getAbsoluteURI(urlOfSource);
+ }
+ catch (Exception e)
+ {
+ // %REVIEW% Is there a better way to send a warning?
+ System.err.println("Can not absolutize URL: " + urlOfSource);
+ }
+ xmlSource.setSystemId(urlOfSource);
+ }
+
+ dtm = new SAX2DTM(this, source, documentID, whiteSpaceFilter,
+ xstringFactory, doIndexing);
+
+ // Add the DTM to the lookup table with offset 0 (start of new DTM).
+ // This needs to be done before any parsing occurs.
+ addDTM(dtm, dtmPos, 0);
+
+ boolean haveXercesParser =
+ (null != reader)
+ && (reader.getClass().getName().equals("org.apache.xerces.parsers.SAXParser") );
+
+ if (haveXercesParser)
+ incremental = true; // No matter what. %REVIEW%
+
+ // If the reader is null, but they still requested an incremental build,
+ // then we still want to set up the IncrementalSAXSource stuff.
+ if (this.m_incremental && incremental /* || ((null == reader) && incremental) */)
+ {
+ IncrementalSAXSource coParser=null;
+
+ if (haveXercesParser)
+ {
+ // IncrementalSAXSource_Xerces to avoid threading.
+ // %REVIEW% Currently this creates a new instance of Xerces, since
+ // there's no way to access the incremental parsing APIs in today's
+ // Xerces. This is wasteful since a reader was already created.
+ // Can we rationalize this flow?
+ try {
+ coParser=org.apache.xml.dtm.ref.IncrementalSAXSource_Xerces.createIncrementalSAXSource();
+ } catch( Exception ex ) {
+ ex.printStackTrace();
+ coParser=null;
+ }
+ }
+
+ if( coParser==null ) {
+ // Create a IncrementalSAXSource that will run on the secondary thread.
if (null == reader)
+ coParser = new IncrementalSAXSource_Filter();
+ else
{
-
- // Then the user will construct it themselves.
- return dtm;
+ IncrementalSAXSource_Filter filter=new IncrementalSAXSource_Filter();
+ filter.setXMLReader(reader);
+ coParser=filter;
}
- // not incremental
- reader.setContentHandler(dtm);
- reader.setDTDHandler(dtm);
- if(null == reader.getErrorHandler())
- reader.setErrorHandler(dtm);
-
- try
- {
- reader.setProperty(
- "http://xml.org/sax/properties/lexical-handler", dtm);
- }
- catch (SAXNotRecognizedException e){}
- catch (SAXNotSupportedException e){}
-
- try
- {
- reader.parse(xmlSource);
- }
- catch (RuntimeException re)
- {
-
- dtm.clearCoRoutine();
-
- throw re;
- }
- catch (Exception e)
- {
-
- dtm.clearCoRoutine();
-
- throw new org.apache.xml.utils.WrappedRuntimeException(e);
- }
}
- if (DUMPTREE)
+ // Have the DTM set itself up as the IncrementalSAXSource's listener.
+ dtm.setIncrementalSAXSource(coParser);
+
+ if (null == xmlSource)
{
- System.out.println("Dumping SAX2DOM");
- dtm.dumpDTM(System.err);
+
+ // Then the user will construct it themselves.
+ return dtm;
}
- return dtm;
+ if(null == reader.getErrorHandler())
+ reader.setErrorHandler(dtm);
+ reader.setDTDHandler(dtm);
+
+ try
+ {
+
+ // Launch parsing coroutine. Launches a second thread,
+ // if we're using IncrementalSAXSource.filter().
+ coParser.startParse(xmlSource);
+ }
+ catch (RuntimeException re)
+ {
+
+ dtm.clearCoRoutine();
+
+ throw re;
+ }
+ catch (Exception e)
+ {
+
+ dtm.clearCoRoutine();
+
+ throw new org.apache.xml.utils.WrappedRuntimeException(e);
+ }
}
else
{
+ if (null == reader)
+ {
- // It should have been handled by a derived class or the caller
- // made a mistake.
- throw new DTMException(XSLMessages.createMessage(XSLTErrorResources.ER_NOT_SUPPORTED, new Object[]{source})); //"Not supported: " + source);
+ // Then the user will construct it themselves.
+ return dtm;
+ }
+
+ // not incremental
+ reader.setContentHandler(dtm);
+ reader.setDTDHandler(dtm);
+ if(null == reader.getErrorHandler())
+ reader.setErrorHandler(dtm);
+
+ try
+ {
+ reader.setProperty(
+ "http://xml.org/sax/properties/lexical-handler", dtm);
+ }
+ catch (SAXNotRecognizedException e){}
+ catch (SAXNotSupportedException e){}
+
+ try
+ {
+ reader.parse(xmlSource);
+ }
+ catch (RuntimeException re)
+ {
+
+ dtm.clearCoRoutine();
+
+ throw re;
+ }
+ catch (Exception e)
+ {
+
+ dtm.clearCoRoutine();
+
+ throw new org.apache.xml.utils.WrappedRuntimeException(e);
+ }
}
+
+ if (DUMPTREE)
+ {
+ System.out.println("Dumping SAX2DOM");
+ dtm.dumpDTM(System.err);
+ }
+
+ return dtm;
+ }
+
+ else
+ {
+
+ // It should have been handled by a derived class or the caller
+ // made a mistake.
+ throw new DTMException(XSLMessages.createMessage(XSLTErrorResources.ER_NOT_SUPPORTED, new Object[]{source})); //"Not supported: " + source);
}
}
@@ -794,10 +894,10 @@
{
System.out.println("Releasing "+
(shouldHardDelete ? "HARD" : "soft")+
- " dtm="+
+ " dtm="+dtm
// Following shouldn't need a nodeHandle, but does...
// and doesn't seem to report the intended value
- dtm.getDocumentBaseURI()
+ +" ("+dtm.getDocumentBaseURI()+")"
);
}
diff --git a/src/org/apache/xml/dtm/ref/DTMNodeList.java b/src/org/apache/xml/dtm/ref/DTMNodeList.java
index 761485e..896035d 100644
--- a/src/org/apache/xml/dtm/ref/DTMNodeList.java
+++ b/src/org/apache/xml/dtm/ref/DTMNodeList.java
@@ -112,10 +112,23 @@
dtm_iter=(DTMIterator)dtmIterator.cloneWithReset();
}
catch(CloneNotSupportedException cnse) {}
- dtm_iter.setShouldCacheNodes(true);
+ dtm_iter.setShouldCache(true);
dtm_iter.runTo(-1);
dtm_iter.setCurrentPos(pos);
}
+
+ /** Public constructor: Create a NodeList to support a XNodeSequenceSingleton.
+ *
+ * @param dtm The DTM containing this node.
+ * @param node node-handle integer.
+ * @param dummy unused.
+ * */
+ public DTMNodeList(DTM dtm,int node, boolean dummy)
+ {
+ dtm_iter=null;
+ m_parentDTM=dtm;
+ m_firstChild=node;
+ }
/** Public constructor: Create a NodeList to support
* DTMNodeProxy.getChildren().
diff --git a/src/org/apache/xml/dtm/ref/ExpandedNameTable.java b/src/org/apache/xml/dtm/ref/ExpandedNameTable.java
index 24bb4b1..0adc7a7 100644
--- a/src/org/apache/xml/dtm/ref/ExpandedNameTable.java
+++ b/src/org/apache/xml/dtm/ref/ExpandedNameTable.java
@@ -77,6 +77,11 @@
* */
public class ExpandedNameTable
{
+ // A bit of a kluge... We want assign-only-once behavior for the
+ // schemaType field, and null is a legitimate value... so we need
+ // a cheap non-null singleton object to use as the not-yet-set flag.
+ // As it happens, almost anything will work...
+ static final Object UNKNOWN_SCHEMA_TYPE=Boolean.FALSE;
/** Probably a reference to static pool. */
private DTMStringPool m_locNamesPool;
@@ -282,12 +287,45 @@
return (short)etype.nodetype;
}
-
+ /** Store the default schema datatype associated with this expanded
+ name.
+
+ @return true if the default has been set (or if the new value
+ matches the old one), false if the new doesn't match (meaning
+ you'd better record this as a per-node exception).
+ */
+ public boolean setSchemaType(int ExpandedNameID, Object schemaType)
+ {
+ ExtendedType et=(ExtendedType)m_extendedTypes.elementAt (ExpandedNameID);
+ if(et.schemaType==UNKNOWN_SCHEMA_TYPE)
+ {
+ et.schemaType=schemaType;
+ return true;
+ }
+ else if(et.schemaType==schemaType ||
+ (et.schemaType!=null && et.schemaType.equals(schemaType)) )
+ return true;
+ else
+ return false;
+ }
+
+ /** @return the default schema datatype associated with this expanded
+ name, null if none has been bound OR if the type bound was itself
+ null.
+ */
+ public Object getSchemaType(int ExpandedNameID)
+ {
+ ExtendedType et=(ExtendedType)m_extendedTypes.elementAt (ExpandedNameID);
+ return (et.schemaType==UNKNOWN_SCHEMA_TYPE) ? null : et.schemaType;
+ }
+
/**
* Private class representing an extended type object
*/
private class ExtendedType
{
+ protected Object schemaType=UNKNOWN_SCHEMA_TYPE;
+
protected int nodetype;
protected String namespace;
protected String localName;
diff --git a/src/org/apache/xml/dtm/ref/IncrementalSAXSource_Xerces.java b/src/org/apache/xml/dtm/ref/IncrementalSAXSource_Xerces.java
index ec02fdf..8be90a9 100644
--- a/src/org/apache/xml/dtm/ref/IncrementalSAXSource_Xerces.java
+++ b/src/org/apache/xml/dtm/ref/IncrementalSAXSource_Xerces.java
@@ -61,13 +61,17 @@
import org.xml.sax.SAXException;
import java.io.IOException;
import org.apache.xerces.parsers.SAXParser;
+import org.apache.xml.utils.WrappedRuntimeException;
import org.xml.sax.XMLReader;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xalan.res.XSLMessages;
import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import javax.xml.transform.TransformerException;
+
/** <p>IncrementalSAXSource_Xerces takes advantage of the fact that Xerces1
* incremental mode is already a coroutine of sorts, and just wraps our
@@ -177,7 +181,41 @@
this.fParseSome=dummy.fParseSome;
this.fIncrementalParser=dummy.fIncrementalParser;
}
- }
+
+ // General SAX-level feature initialization
+ try
+ {
+ fIncrementalParser.setFeature("http://xml.org/sax/features/validation",true);
+ }
+ catch(org.xml.sax.SAXNotRecognizedException e) {e.printStackTrace();}
+ catch(org.xml.sax.SAXNotSupportedException e) {e.printStackTrace();}
+ try
+ {
+ fIncrementalParser.setFeature("http://apache.org/xml/features/validation/dynamic",true);
+ }
+ catch(org.xml.sax.SAXNotRecognizedException e) {e.printStackTrace();}
+ catch(org.xml.sax.SAXNotSupportedException e) {e.printStackTrace();}
+
+ // %REVIEW% Turning on schema support is necessary for some
+ // of the information we'd like to retrieve. Unfortunately,
+ // XERCES currently slows down by 90% (ie, takes twice as
+ // long to run!) with this feature enabled, even if the
+ // document never references schemas. We could make this
+ // optional (resurrect the old -VALIDATE switch?), but it's
+ // really not clear we want the user to have to deal with
+ // manually setting this appropriately for every document.
+ // The default would have to be full validation, slow mode.
+ //
+ // I'm trying to convince Xerces that higher speed should be
+ // given higher priority.
+ try
+ {
+ fIncrementalParser.setFeature("http://apache.org/xml/features/validation/schema",true);
+ }
+ catch(org.xml.sax.SAXNotRecognizedException e) {e.printStackTrace();}
+ catch(org.xml.sax.SAXNotSupportedException e) {e.printStackTrace();}
+
+ }
/** Create a IncrementalSAXSource_Xerces wrapped around
* an existing SAXParser. Currently this works only for recent
@@ -348,7 +386,39 @@
return arg;
}
- // Private methods -- conveniences to hide the reflection details
+ static final Object[] parmstrue={Boolean.TRUE};
+
+ /** deliverAllNodes() is a simple API which tells the coroutine
+ * parser to run until all nodes have been delivered.
+ * This is a bit of a kluge, intended to address the case where
+ * we're using IncrementalSAXSource_Xerces not for its incrementality
+ * but as a wrapper around the Xerces XNI layer; its primary purpose
+ * is to simplify the logic in DTMManagerDefault.java
+ * */
+ public void deliverAllNodes() throws SAXException
+ {
+ try
+ {
+ Object ret =
+ (Boolean) (fConfigParse.invoke(fPullParserConfig, parmstrue));
+ }
+ catch (IllegalAccessException iae)
+ {
+ throw new WrappedRuntimeException(
+ new TransformerException(iae));
+ }
+ catch (InvocationTargetException ite)
+ {
+ throw new WrappedRuntimeException(
+ new TransformerException(ite.getTargetException()));
+ }
+ catch (RuntimeException ex)
+ {
+ throw new WrappedRuntimeException(new TransformerException(ex));
+ }
+ }
+
+ // Private methods -- conveniences to hide the reflection details
private boolean parseSomeSetup(InputSource source)
throws SAXException, IOException, IllegalAccessException,
java.lang.reflect.InvocationTargetException,
@@ -479,6 +549,18 @@
}
}
+
+ /** EXPERIMENTAL AS OF 3/22/02: Support for XNI2DTM, allowing us to
+ * bind direct to the parser's XNI stream.
+ *
+ * %BUG% Gonk -- This requires hard link to Xerces2. Could use reflection
+ * typecasting, but for now... Does anyone still care about Xerces1?
+ * */
+ public org.apache.xerces.xni.parser.XMLPullParserConfiguration getXNIParserConfiguration()
+ {
+ return (org.apache.xerces.xni.parser.XMLPullParserConfiguration)fPullParserConfig;
+ }
+
} // class IncrementalSAXSource_Xerces
diff --git a/src/org/apache/xml/dtm/ref/dom2dtm/DOM2DTM.java b/src/org/apache/xml/dtm/ref/dom2dtm/DOM2DTM.java
index 80eb115..0ae8473 100644
--- a/src/org/apache/xml/dtm/ref/dom2dtm/DOM2DTM.java
+++ b/src/org/apache/xml/dtm/ref/dom2dtm/DOM2DTM.java
@@ -94,6 +94,9 @@
* Note too that we do not currently attempt to track document
* mutation. If you alter the DOM after wrapping DOM2DTM around it,
* all bets are off.
+ * %REVIEW% We _could_ ask the DOM whether it supports mutation
+ * events, and if so use that to invalidate the DTM or at least
+ * toss a warning back into Xalan...
* */
public class DOM2DTM extends DTMDefaultBaseIterators
{
diff --git a/src/org/apache/xml/dtm/ref/sax2dtm/SAX2DTM.java b/src/org/apache/xml/dtm/ref/sax2dtm/SAX2DTM.java
index 57e0e13..aeb7c06 100644
--- a/src/org/apache/xml/dtm/ref/sax2dtm/SAX2DTM.java
+++ b/src/org/apache/xml/dtm/ref/sax2dtm/SAX2DTM.java
@@ -82,6 +82,12 @@
/**
* This class implements a DTM that tends to be optimized more for speed than
* for compactness, that is constructed via SAX2 ContentHandler events.
+ *
+ * NOTE: This version of the code incorporates the logic needed to allow
+ * "shared DTMs", where a single DTM contains several documents which may
+ * be tail-pruned away. This mode is used for result tree
+ * fragments/temporary trees. A separate constructor *must* be used to
+ * invoke this mode.
*/
public class SAX2DTM extends DTMDefaultBaseIterators
implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler,
@@ -89,6 +95,14 @@
{
/** Set true to monitor SAX events and similar diagnostic info. */
private static final boolean DEBUG = false;
+
+ /** See discussion in endDocument() */
+ static final boolean JJK_LEAVE_DOCUMENT_CURRENT=false;
+
+ /** Set true when the DTM goes into Shared DTM mode -- specifically, when
+ * the shared-mode constructor is invoked.
+ * */
+ private boolean m_isSharedDTM=false;
/**
* If we're building the model incrementally on demand, we need to
@@ -116,11 +130,26 @@
* between RTFs, and tail-pruning... consider going back to the larger/faster.
*
* Made protected rather than private so SAX2RTFDTM can access it.
+ * Minimum chunk size pushed up now that SAX2RTFDTM is in use (larger
+ * minimum allocation, lower overhead as it grows).
+ * %REVIEW% Variable size disabled in FSB. Consider (13,13).
*/
- //private FastStringBuffer m_chars = new FastStringBuffer(13, 13);
- protected FastStringBuffer m_chars = new FastStringBuffer(5, 13);
+ protected FastStringBuffer m_chars = new FastStringBuffer(10, 13);
- /** This vector holds offset and length data.
+ /** This vector holds _integer pairs_ representing the "node value"
+ * referenced by m_dataOrQName. It's basically a kluge to save a word
+ * per node for nodes which don't carry this information... AND is
+ * overloaded to handle two distinct cases.
+ *
+ * In: index (and index+1) from m_dataOrQName
+ *
+ * Out: Offset and length references into m_chars (for character content)
+ * ***OR***
+ * (IF m_dataOrQName returned a negated index for an Attr node,
+ * indicating a prefixed attribute):
+ * m_valuesOrPrefixes identifiers of prefix and value
+ *
+ * %REVIEW% Is this really the best solution? I hae me doots!
*/
protected SuballocatedIntVector m_data;
@@ -164,7 +193,7 @@
protected DTMTreeWalker m_walker = new DTMTreeWalker();
/** pool of string values that come as strings. */
- private DTMStringPool m_valuesOrPrefixes = new DTMStringPool();
+ protected DTMStringPool m_valuesOrPrefixes = new DTMStringPool();
/** End document has been reached.
* Made protected rather than private so SAX2RTFDTM can access it.
@@ -237,9 +266,34 @@
*/
protected IntVector m_sourceColumn;
+ /** Index of most recently started Document, or NULL if the DTM is shared and empty. */
+ private int m_currentDocumentNode=0;
+
+ /** Tail-pruning mark: Number of nodes in use. Null if not a shared DTM. */
+ IntStack mark_size=null;
+ /** Tail-pruning mark: Number of data items in use. Null if not a shared DTM. */
+ IntStack mark_data_size=null;
+ /** Tail-pruning mark: Number of size-of-data fields in use. Null if not a shared DTM. */
+ IntStack mark_char_size=null;
+ /** Tail-pruning mark: Number of dataOrQName slots in use. Null if not a shared DTM. */
+ IntStack mark_doq_size=null;
+ /** Tail-pruning mark: Number of namespace declaration sets in use. Null if not a shared DTM.
+ * %REVIEW% I don't think number of NS sets is ever different from number
+ * of NS elements. We can probabably reduce these to a single stack and save
+ * some storage.
+ * */
+ IntStack mark_nsdeclset_size=null;
+ /** Tail-pruning mark: Number of namespace declaration elements in use. Null if not a shared DTM.
+ * %REVIEW% I don't think number of NS sets is ever different from number
+ * of NS elements. We can probabably reduce these to a single stack and save
+ * some storage.
+ */
+ IntStack mark_nsdeclelem_size=null;
+
/**
* Construct a SAX2DTM object ready to be constructed from SAX2
- * ContentHandler events.
+ * ContentHandler events. DTMs produced by this constructor do _NOT_
+ * support shared mode.
*
* @param mgr The DTMManager who owns this DTM.
* @param source the JAXP 1.1 Source object for this DTM.
@@ -261,8 +315,10 @@
// %REVIEW% Initial size pushed way down to reduce weight of RTFs
// (I'm not entirely sure 0 would work, so I'm playing it safe for now.)
+ // %REVIEW% Given shared RTF DTM, we might be able to push this
+ // back up again...?
//m_data = new SuballocatedIntVector(doIndexing ? (1024*2) : 512, 1024);
- m_data = new SuballocatedIntVector(32, 1024);
+ m_data = new SuballocatedIntVector(32);
m_data.addElement(0); // Need placeholder in case index into here must be <0.
@@ -279,6 +335,57 @@
}
/**
+ * Construct a SAX2DTM object ready to be constructed from SAX2
+ * ContentHandler events. DTMs produced by this constructor may support
+ * shared mode.
+ *
+ * @param mgr The DTMManager who owns this DTM.
+ * @param source the JAXP 1.1 Source object for this DTM.
+ * @param dtmIdentity The DTM identity ID for this DTM.
+ * @param whiteSpaceFilter The white space filter for this DTM, which may
+ * be null.
+ * @param xstringfactory XMLString factory for creating character content.
+ * @param doIndexing true if the caller considers it worth it to use
+ * indexing schemes. HOWEVER: Indexes may be suppressed if shared is
+ * true, since they tend to be hard to prune efficiently.
+ * @param shared true if the caller may want to write multiple documents
+ * into this DTM and prune them away again. This should be set true
+ * only for Result-Tree-Fragment/Temporary-Tree DTMs.
+ */
+ public SAX2DTM(DTMManager mgr, Source source, int dtmIdentity,
+ DTMWSFilter whiteSpaceFilter,
+ XMLStringFactory xstringfactory,
+ boolean doIndexing, boolean shared)
+ {
+ // Normal construction. Note doIndexing forced false when shared is true.
+ this(mgr, source, dtmIdentity, whiteSpaceFilter, xstringfactory,
+ doIndexing & !shared);
+
+ m_isSharedDTM=shared;
+
+ if(shared)
+ {
+ // NEVER track source locators for RTFs; they aren't meaningful. I think.
+ // (If we did track them, we'd need to tail-prune these too.)
+ m_useSourceLocationProperty=false; //org.apache.xalan.processor.TransformerFactoryImpl.m_source_location;
+ m_sourceSystemId = null;
+ m_sourceLine = null;
+ m_sourceColumn = null;
+
+ // Initialize data structures for tail-pruning
+ mark_size=new IntStack();
+ mark_data_size=new IntStack();
+ mark_char_size=new IntStack();
+ mark_doq_size=new IntStack();
+ mark_nsdeclset_size=new IntStack();
+ mark_nsdeclelem_size=new IntStack();
+
+ // Safety-net, to help make sure we're using this as intended
+ m_currentDocumentNode=NULL;
+ }
+ }
+
+ /**
* Get the data or qualified name for the given node identity.
*
* @param identity The node identity.
@@ -304,6 +411,32 @@
return m_dataOrQName.elementAt(identity);
}
}
+
+ /**
+ * Given a node identifier, find the owning document node. Unlike the DOM,
+ * this considers the owningDocument of a Document to be itself. Note that
+ * in shared DTMs this may be nonzero.
+ *
+ * @param nodeId the id of the node.
+ * @return int Node identifier of owning document, or the nodeId if it is
+ * a Document.
+ */
+ protected int _documentRoot(int nodeIdentifier)
+ {
+ if(nodeIdentifier==NULL) return NULL;
+
+ if(!m_isSharedDTM)
+ return 0;
+
+ // Otherwise, shared DTM and we have to do this the slow way.
+ for(int parent=_parent(nodeIdentifier);
+ parent!=NULL;
+ nodeIdentifier=parent,parent=_parent(nodeIdentifier))
+ ;
+
+ return nodeIdentifier;
+ }
+
/**
* Ask the CoRoutine parser to doTerminate and clear the reference.
@@ -569,8 +702,7 @@
{
int expandedTypeID = getExpandedTypeID(nodeHandle);
- // If just testing nonzero, no need to shift...
- int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);
+ int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);
if (0 == namespaceID)
{
@@ -617,8 +749,8 @@
public String getNodeNameX(int nodeHandle)
{
- int expandedTypeID = getExpandedTypeID(nodeHandle);
- int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);
+ int expandedTypeID = getExpandedTypeID(nodeHandle);
+ int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);
if (0 == namespaceID)
{
@@ -690,13 +822,13 @@
identity += 1;
- while (identity >= m_size)
- {
- if (null == m_incrementalSAXSource)
- return DTM.NULL;
+ while (identity >= m_size && nextNode())
+ ;
- nextNode();
- }
+ // If we exited because nextNode ran off the end of the document,
+ // rather than because we found the node we needed, return null.
+ if(identity>=m_size)
+ return DTM.NULL;
return identity;
}
@@ -746,8 +878,13 @@
/**
* This method should try and build one or more nodes in the table.
+ *
+ * %OPT% When working with Xerces2, an incremental parsing step may not
+ * actually generate a SAX event that causes a node to be built. Our higher-
+ * level code is already looping to see if the desired node was obtained...
+ * but should we also be looping more tightly here?
*
- * @return The true if a next node is found or false if
+ * @return True if parsing proceeded normally or false if
* there are no more nodes.
*/
protected boolean nextNode()
@@ -1103,6 +1240,12 @@
return getPrefix(qname, null);
}
}
+ else if (DTM.NAMESPACE_NODE == type)
+ {
+ if(!"xmlns".equals(getLocalName(nodeHandle)))
+ return "xmlns";
+ // else return "".
+ }
return "";
}
@@ -1138,6 +1281,54 @@
return DTM.NULL;
}
+
+ /**
+ * Given a DTM, find the owning document node. In the case of
+ * SAX2RTFDTM, which may contain multiple documents, this returns
+ * the <b>most recently started</b> document, or null if the DTM is
+ * empty or no document is currently under construction.
+ *
+ * %REVIEW% Should we continue to report the most recent after
+ * construction has ended? I think not, given that it may have been
+ * tail-pruned.
+ *
+ * @param nodeHandle the id of the node.
+ * @return int Node handle of Document node, or null if this DTM does not
+ * contain an "active" document.
+ * */
+ public int getDocument()
+ {
+ // %REVIEW% Would adding these lines affect speed, and if so which way?
+ // if(!m_isSharedDTM)
+ // return m_dtmIdent.elementAt(0); // like DTMDefaultBase
+ return makeNodeHandle(m_currentDocumentNode);
+ }
+
+ /**
+ * Given a node handle, find the owning document node, using DTM semantics
+ * (Document owns itself) rather than DOM semantics (Document has no owner).
+ *
+ * (I'm counting on the fact that getOwnerDocument() is implemented on top
+ * of this call, in the superclass, to avoid having to rewrite that one.
+ * Be careful if that code changes!)
+ *
+ * @param nodeHandle the id of the node.
+ * @return int Node handle of owning document
+ */
+ public int getDocumentRoot(int nodeHandle)
+ {
+ if(!m_isSharedDTM)
+ return getDocument();
+
+ // If shared, we have to do it the hard way
+ for(int id=makeNodeIdentity(nodeHandle);
+ id!=NULL;
+ id=_parent(id))
+ if(_type(id)==DTM.DOCUMENT_NODE)
+ return makeNodeHandle(id);
+
+ return DTM.NULL; // Safety net; should never happen
+ }
/**
* Return the public identifier of the external subset,
@@ -1171,8 +1362,13 @@
*/
public String getNamespaceURI(int nodeHandle)
{
+ int identity=makeNodeIdentity(nodeHandle);
+
+ // DOM says all namespace nodes are in the namespace namespace.
+ if (_type(identity) == NAMESPACE_NODE)
+ return "http://www.w3.org/XML/1998/namespace";
- return m_expandedNameTable.getNamespace(_exptype(makeNodeIdentity(nodeHandle)));
+ return m_expandedNameTable.getNamespace(_exptype(identity));
}
/**
@@ -1302,7 +1498,7 @@
*
* @return The prefix if there is one, or null.
*/
- private String getPrefix(String qname, String uri)
+ protected String getPrefix(String qname, String uri)
{
String prefix;
@@ -1545,6 +1741,18 @@
{
if (DEBUG)
System.out.println("startDocument");
+
+ if(m_isSharedDTM)
+ {
+ // (Re)initialize the tree construction process
+ // %REVIEW% Slightly wasteful on the first document written to
+ // the shared DTM, since these have already been allocated.
+ m_endDocumentOccured = false;
+ m_prefixMappings = new java.util.Vector();
+ m_contextIndexes = new IntStack();
+ m_parents = new IntStack();
+ m_currentDocumentNode=m_size;
+ }
int doc = addNode(DTM.DOCUMENT_NODE,
@@ -1569,12 +1777,12 @@
if (DEBUG)
System.out.println("endDocument");
- charactersFlush();
+ charactersFlush();
- m_nextsib.setElementAt(NULL,0);
+ m_nextsib.setElementAt(NULL,m_currentDocumentNode);
- if (m_firstch.elementAt(0) == NOTPROCESSED)
- m_firstch.setElementAt(NULL,0);
+ if (m_firstch.elementAt(m_currentDocumentNode) == NOTPROCESSED)
+ m_firstch.setElementAt(NULL,m_currentDocumentNode);
if (DTM.NULL != m_previous)
m_nextsib.setElementAt(DTM.NULL,m_previous);
@@ -1583,6 +1791,15 @@
m_prefixMappings = null;
m_contextIndexes = null;
+ // This is debatable. Clearing it in shared DTMs does help keep
+ // us honest, by ensuring against using getDocument() in a situation
+ // where we aren't sure which document is being referred to.
+ // We _shouldn't_ clear it in non-shared DTMs, since -- at this time,
+ // anyway -- some of the start-up code assumes that getDocument() on the
+ // source document will work after the doc is closed.
+ if(!JJK_LEAVE_DOCUMENT_CURRENT && m_isSharedDTM)
+ m_currentDocumentNode= NULL; // no longer open
+
m_endDocumentOccured = true;
}
@@ -1679,7 +1896,7 @@
return false;
}
- boolean m_pastFirstElement=false;
+ protected boolean m_pastFirstElement=false;
/**
* Receive notification of the start of an element.
@@ -2349,4 +2566,100 @@
}
return null;
}
+
+ /** "Tail-pruning" support for RTFs.
+ *
+ * This function pushes information about the current size of the
+ * DTM's data structures onto a stack, for use by popRewindMark()
+ * (which see).
+ *
+ * This will fail with null-pointer exceptions if called on a non-shared
+ * DTM. That's deliberate, since it's considered a severe coding error.
+ *
+ * %REVIEW% I have no idea how to rewind m_elemIndexes. However,
+ * RTFs should not be indexed, so I can simply panic if that case
+ * arises. Hey, it works...
+ * */
+ public void pushRewindMark()
+ {
+ if(m_indexing || m_elemIndexes!=null)
+ throw new java.lang.NullPointerException("Coding error; Don't try to mark/rewind an indexed DTM");
+
+ // Values from DTMDefaultBase
+ // %REVIEW% Can the namespace stack sizes ever differ? If not, save space!
+ mark_size.push(m_size);
+ mark_nsdeclset_size.push( (m_namespaceDeclSets==null) ? 0 : m_namespaceDeclSets.size() );
+ mark_nsdeclelem_size.push( (m_namespaceDeclSetElements==null) ? 0 : m_namespaceDeclSetElements.size() );
+
+ // Values from SAX2DTM
+ mark_data_size.push(m_data.size());
+ mark_char_size.push(m_chars.size());
+ mark_doq_size.push(m_dataOrQName.size());
+ }
+
+ /** "Tail-pruning" support for RTFs.
+ *
+ * This function pops the information previously saved by
+ * pushRewindMark (which see) and uses it to discard all nodes added
+ * to the DTM after that time. We expect that this will allow us to
+ * reuse storage more effectively.
+ *
+ * This is _not_ intended to be called while a document is still being
+ * constructed -- only between endDocument and the next startDocument
+ *
+ * %REVIEW% WARNING: This is the first use of some of the truncation
+ * methods. If Xalan blows up after this is called, that's a likely
+ * place to check.
+ *
+ * %REVIEW% Our original design for DTMs permitted them to share
+ * string pools. If there any risk that this might be happening, we
+ * can _not_ rewind and recover the string storage. One solution
+ * might to assert that DTMs used for RTFs Must Not take advantage
+ * of that feature, but this seems excessively fragile. Another, much
+ * less attractive, would be to just let them leak... Nah.
+ *
+ * This will fail with null-pointer exceptions if called on a non-shared
+ * DTM. That's deliberate, since it's considered a severe coding error.
+ *
+ * @return true if and only if the pop completely emptied the
+ * RTF. That response is used when determining how to unspool
+ * RTF-started-while-RTF-open situations.
+ * */
+ public boolean popRewindMark()
+ {
+ boolean top=mark_size.empty();
+
+ m_size=top ? 0 : mark_size.pop();
+ m_exptype.setSize(m_size);
+ m_firstch.setSize(m_size);
+ m_nextsib.setSize(m_size);
+ m_prevsib.setSize(m_size);
+ m_parent.setSize(m_size);
+
+ m_elemIndexes=null;
+
+ int ds= top ? 0 : mark_nsdeclset_size.pop();
+ if (m_namespaceDeclSets!=null)
+ m_namespaceDeclSets.setSize(ds);
+
+ int ds1= top ? 0 : mark_nsdeclelem_size.pop();
+ if (m_namespaceDeclSetElements!=null)
+ m_namespaceDeclSetElements.setSize(ds1);
+
+ // Values from SAX2DTM
+ m_data.setSize(top ? 0 : mark_data_size.pop());
+ m_chars.setLength(top ? 0 : mark_char_size.pop());
+ m_dataOrQName.setSize(top ? 0 : mark_doq_size.pop());
+
+ // Return true iff DTM now empty
+ return m_size==0;
+ }
+
+ /** @return true if a DTM tree is currently under construction.
+ * */
+ public boolean isTreeIncomplete()
+ {
+ return !m_endDocumentOccured;
+
+ }
}
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/AbstractSchema.java b/src/org/apache/xml/dtm/ref/xni2dtm/AbstractSchema.java
new file mode 100644
index 0000000..d8445a3
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/AbstractSchema.java
@@ -0,0 +1,191 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import org.apache.xml.dtm.*;
+import org.w3c.dom.*;
+
+import org.apache.xerces.xni.*;
+import org.apache.xerces.xni.psvi.*;
+import org.apache.xerces.xni.grammars.XMLGrammarPool;
+
+
+/** This is a vague -- very vague -- attempt to encapsulate the XPath2
+ * "in-scope schema definitions". Our only available implementation at this
+ * time is highly Xerces-dependent, but I'd really rather not expose that
+ * more widely than I have to.
+ *
+ * This is supposed to be a set of (QName, type definition) pairs, defining the set
+ * of types available for reference within XPath expressions, including
+ * the validate() operation. PLEASE NOTE that these make absolutely no
+ * reference to the types referenced by the instance document, though the
+ * two sets are expected/hoped to overlap.
+ *
+ * The built-in schema types should always be available. Additional schema
+ * documents can be loaded into the mix.
+ *
+ * %REVIEW% Many issues -- base URI, you-name-it.
+ * */
+public class AbstractSchema {
+ org.apache.xerces.impl.xs.XMLSchemaLoader xsload=
+ new org.apache.xerces.impl.xs.XMLSchemaLoader();
+ org.apache.xerces.util.XMLGrammarPoolImpl pool=
+ new org.apache.xerces.util.XMLGrammarPoolImpl();
+
+ public AbstractSchema()
+ {
+ // Apparently required to bind the two together, per Neil G.
+ // This implies pool.putGrammar will be called after loading.
+ xsload.setProperty(DOMValidationConfigurationSwipedFromXerces.GRAMMAR_POOL,pool);
+ }
+
+ public void appendSchema(String publicId, String systemId,
+ String baseSystemId, java.io.InputStream byteStream,
+ String encoding)
+ {
+ if(publicId==null) publicId="";
+ if(systemId==null) systemId="";
+ if(baseSystemId==null) baseSystemId="";
+ try
+ {
+ org.apache.xerces.xni.grammars.Grammar gmr=
+ xsload.loadGrammar(
+ new org.apache.xerces.xni.parser.XMLInputSource(
+ publicId, systemId, baseSystemId, byteStream, encoding));
+ }
+ catch (java.io.IOException e)
+ {
+ // DO SOMETHING WITH THIS!
+ System.err.println(e);
+ }
+ }
+ public void appendSchema(String publicId, String systemId,
+ String baseSystemId, java.io.Reader charStream,
+ String encoding)
+ {
+ if(publicId==null) publicId="";
+ if(systemId==null) systemId="";
+ if(baseSystemId==null) baseSystemId="";
+ try
+ {
+ org.apache.xerces.xni.grammars.Grammar gmr=
+ xsload.loadGrammar(
+ new org.apache.xerces.xni.parser.XMLInputSource(
+ publicId, systemId, baseSystemId, charStream, encoding));
+ }
+ catch (java.io.IOException e)
+ {
+ // DO SOMETHING WITH THIS!
+ System.err.println(e);
+ }
+ }
+ public void appendSchema(String publicId, String systemId,
+ String baseSystemId)
+ {
+ if(publicId==null) publicId="";
+ if(systemId==null) systemId="";
+ if(baseSystemId==null) baseSystemId="";
+ try
+ {
+ // %REVIEW% Need more education on loading grammars; this is a kluge
+ // Need to set an error handler on this.
+ // Should we really reset every time?
+ xsload.reset();
+
+ org.apache.xerces.xni.grammars.Grammar gmr=
+ xsload.loadGrammar(
+ new org.apache.xerces.xni.parser.XMLInputSource(
+ publicId, systemId, baseSystemId));
+ }
+ catch (java.io.IOException e)
+ {
+ // DO SOMETHING WITH THIS!
+ System.err.println(e);
+ }
+ }
+
+ public Object getGrammarPool()
+ {
+ return pool;
+ }
+
+ /** This relies on unpublished Xerces APIs. It's even more vulnerable
+ * to future change than the rest of the PSVI interfaces.
+ * Caveat hackitor!
+ *
+ * Outline courtesy of Sandy Gao -- thanks again!
+ * */
+ public XPath2Type lookUpType(String namespace,String typename)
+ {
+ XPath2Type ret=null;
+
+ org.apache.xerces.impl.xs.XSDDescription descr=
+ new org.apache.xerces.impl.xs.XSDDescription();
+ descr.setContextType(descr.CONTEXT_PREPARSE);
+ if(namespace==null) namespace=""; // I *think* this is right; not sure
+ descr.setTargetNamespace(namespace);
+
+ org.apache.xerces.xni.grammars.Grammar g=pool.getGrammar(descr);
+ if(g!=null)
+ ret=new XPath2Type( ((org.apache.xerces.impl.xs.SchemaGrammar)g).getGlobalTypeDecl(typename),
+ namespace,typename);
+
+ return ret;
+ }
+
+}
+
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/DOMValidationConfigurationSwipedFromXerces.java b/src/org/apache/xml/dtm/ref/xni2dtm/DOMValidationConfigurationSwipedFromXerces.java
new file mode 100644
index 0000000..d71bf79
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/DOMValidationConfigurationSwipedFromXerces.java
@@ -0,0 +1,558 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001, 2002 The Apache Software Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xerces" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, International
+ * Business Machines, Inc., http://www.apache.org. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.impl.XMLEntityManager;
+import org.apache.xerces.impl.XMLErrorReporter;
+import org.apache.xerces.impl.validation.ValidationManager;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.impl.xs.XSMessageFormatter;
+import org.apache.xerces.util.ParserConfigurationSettings;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.xni.XMLDocumentHandler;
+import org.apache.xerces.xni.XMLDTDHandler;
+import org.apache.xerces.xni.XMLDTDContentModelHandler;
+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.XMLDocumentSource;
+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;
+
+/**
+ * This configuration holds information needed for revalidation
+ * of the DOM tree, ie. properties and features.
+ * Note: This configuration is different from any parser
+ * configuration and must not be used other than for DOM revalidation.
+ *
+ * @author Elena Litani, IBM
+ * @version $Id$
+ */
+public class DOMValidationConfigurationSwipedFromXerces extends ParserConfigurationSettings
+ implements XMLParserConfiguration {
+
+ //
+ // Constants
+ //
+
+ // feature identifiers
+
+ /** Feature identifier: validation. */
+ public 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;
+
+ public static final String SCHEMA =
+ Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
+
+ 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;
+
+
+
+ // 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*/
+ public static final String GRAMMAR_POOL =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_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;
+
+
+ protected static final String VALIDATION_MANAGER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
+ //
+ // Data
+ //
+ XMLDocumentHandler fDocumentHandler;
+
+ // components (non-configurable)
+
+ /** Symbol table. */
+ protected SymbolTable fSymbolTable;
+
+ // data
+
+ /** Components. */
+ protected Vector fComponents;
+
+
+ /** Locale. */
+ protected Locale fLocale;
+ protected XMLErrorReporter fErrorReporter;
+
+ //
+ // Constructors
+ //
+
+ /** Default Constructor. */
+ public DOMValidationConfigurationSwipedFromXerces() {
+ this(null, null);
+ } // <init>()
+
+ /**
+ * Constructs a parser configuration using the specified symbol table.
+ *
+ * @param symbolTable The symbol table to use.
+ */
+ public DOMValidationConfigurationSwipedFromXerces(SymbolTable symbolTable) {
+ this(symbolTable, null);
+ } // <init>(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.
+ */
+ public DOMValidationConfigurationSwipedFromXerces(SymbolTable symbolTable,
+ XMLComponentManager parentSettings) {
+ super(parentSettings);
+
+ // create storage for recognized features and properties
+ fRecognizedFeatures = new Vector();
+ fRecognizedProperties = new Vector();
+
+ // create table for features and properties
+ fFeatures = new Hashtable();
+ fProperties = new Hashtable();
+
+ // add default recognized features
+ final String[] recognizedFeatures = {
+ VALIDATION,
+ NAMESPACES,
+ SCHEMA,
+ DYNAMIC_VALIDATION,
+ NORMALIZE_DATA
+ };
+ addRecognizedFeatures(recognizedFeatures);
+
+ // set state for default features
+ setFeature(VALIDATION, false);
+ setFeature(SCHEMA, false);
+ setFeature(DYNAMIC_VALIDATION, false);
+ setFeature(NORMALIZE_DATA, true);
+ setFeature(NAMESPACES, true);
+
+ // add default recognized properties
+ final String[] recognizedProperties = {
+ XML_STRING,
+ SYMBOL_TABLE,
+ ERROR_HANDLER,
+ ENTITY_RESOLVER,
+ ERROR_REPORTER,
+ ENTITY_MANAGER,
+ VALIDATION_MANAGER,
+ GRAMMAR_POOL
+ };
+ addRecognizedProperties(recognizedProperties);
+
+ if (symbolTable == null) {
+ symbolTable = new SymbolTable();
+ }
+ fSymbolTable = symbolTable;
+
+ fComponents = new Vector();
+
+ setProperty(SYMBOL_TABLE, fSymbolTable);
+ fErrorReporter = new XMLErrorReporter();
+ setProperty(ERROR_REPORTER, fErrorReporter);
+ addComponent(fErrorReporter);
+
+ XMLEntityManager manager = new XMLEntityManager();
+ setProperty(ENTITY_MANAGER, manager);
+ addComponent(manager);
+
+ setProperty(VALIDATION_MANAGER, new ValidationManager());
+
+
+ // 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);
+ }
+
+ if (fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN) == null) {
+ XSMessageFormatter xmft = new XSMessageFormatter();
+ fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, xmft);
+ }
+
+
+ // set locale
+ try {
+ setLocale(Locale.getDefault());
+ }
+ catch (XNIException e) {
+ // do nothing
+ // REVISIT: What is the right thing to do? -Ac
+ }
+
+
+ } // <init>(SymbolTable)
+
+
+ //
+ // XMLParserConfiguration methods
+ //
+
+ /**
+ * Parse an XML document.
+ * <p>
+ * 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).
+ * <p>
+ * 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.
+ * <p>
+ * 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 source 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) {
+ if (resolver !=null) {
+ 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.
+ *
+ * <p>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.</p>
+ *
+ * <p>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.</p>
+ *
+ * @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() {
+ // REVISIT: Should this be a property?
+ return (XMLErrorHandler)fProperties.get(ERROR_HANDLER);
+ } // getErrorHandler():XMLErrorHandler
+
+ /**
+ * 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
+
+ //
+ // Protected methods
+ //
+
+ /**
+ * reset all components before parsing
+ */
+ protected void reset() throws XNIException {
+
+ int count = fComponents.size();
+ for (int i = 0; i < count; i++) {
+ XMLComponent c = (XMLComponent) fComponents.elementAt(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)) {
+ String property =
+ propertyId.substring(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 (property.equals(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)
+
+
+ public void addComponent(XMLComponent component) {
+
+ // don't add a component more than once
+ if (fComponents.contains(component)) {
+ return;
+ }
+ fComponents.addElement(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)
+
+
+} // class XMLParser
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/DTM2XNI.java b/src/org/apache/xml/dtm/ref/xni2dtm/DTM2XNI.java
new file mode 100644
index 0000000..108d742
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/DTM2XNI.java
@@ -0,0 +1,622 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import org.apache.xml.dtm.*;
+import org.w3c.dom.*;
+
+import org.apache.xml.utils.NodeConsumer;
+import org.apache.xml.utils.XMLString;
+
+import org.apache.xerces.xni.*;
+import org.apache.xerces.xni.psvi.*;
+
+/**
+ * <meta name="usage" content="advanced"/>
+ * This class does a pre-order walk of the DTM tree, calling an XNI
+ * XMLDocumentHandler interface as it goes. As such, it's more like
+ * the Visitor design pattern than like the DOM's TreeWalker.
+ */
+public class DTM2XNI
+implements org.apache.xerces.xni.parser.XMLDocumentScanner
+{
+ /** Set true if xsi:type and xsi:schemaLocation should _not_ be serialized.
+ * (Sets them aside into annotations.)
+ * This flag is also referenced in XNI2DTM
+ * */
+ public static boolean SUPPRESS_XSI_ATTRIBUTES=true;
+
+ /** Local reference to a XMLDocumentHandler */
+ private XMLDocumentHandler m_XMLDocumentHandler = null;
+
+ /** Source for this TreeWalker */
+ protected DTM m_dtm;
+
+ /** Source for this TreeWalker */
+ protected int m_root;
+
+ /** Context to wrap around this TreeWalker */
+ protected java.util.Vector m_context;
+
+ /** Buffer for chars going out to the handler. Reusable.
+ * WARNING: o..a..xerces.xni.XMLString and o..a..xml.utils.XNIString
+ * are *NOT* the same thing! */
+ protected org.apache.xerces.xni.XMLString m_xnistring=new org.apache.xerces.xni.XMLString();
+
+ /** Buffer for augmentations. Reusable.
+ * WARNING: XNI _will_ add values to this; be prepared to
+ * clear and reinstantiate it every time.
+ * */
+ protected org.apache.xerces.xni.Augmentations m_augs=
+ new org.apache.xerces.util.AugmentationsImpl();
+
+ /** Manefest constant: Augmentation flag for structure we added, which
+ * may need to be stripped out again after validation
+ * This flag is also referenced in XNI2DTM
+ * */
+ public static final String DTM2XNI_ADDED_STRUCTURE="Synthetic-Node-added-by-org.apache.xml.dtm.ref.xni2dtm.DTM2XNI";
+
+ /** Manafest constant: XML Schema Instance namespace
+ * This constant is also referenced in XNI2DTM
+ * */
+ static final String XSI_NAMESPACE="http://www.w3.org/2001/XMLSchema-instance";
+
+ /** Manefest constant: Annotation for suppressed xsi:
+ * This constant is also referenced in XNI2DTM
+ * */
+ public static final String SUPPRESSED_XSI="XSI-directive-suppressed-by-org.apache.xml.dtm.ref.xni2dtm.DTM2XNI";
+
+ /**
+ * Set the DTM to be traversed.
+ *
+ * @param dtm Document Table Model to be used.
+ */
+ public void setDTM(DTM dtm)
+ {
+ m_dtm = dtm;
+ }
+
+ /**
+ * Get the XMLDocumentHandler used for the tree walk.
+ *
+ * @return the XMLDocumentHandler used for the tree walk
+ */
+ public XMLDocumentHandler getXMLDocumentHandler()
+ {
+ return m_XMLDocumentHandler;
+ }
+
+ /**
+ * Set the XMLDocumentHandler used for the tree walk.
+ *
+ * @param ch the XMLDocumentHandler to be the result of the tree walk.
+ */
+ public void setXMLDocumentHandler(XMLDocumentHandler ch)
+ {
+ m_XMLDocumentHandler = ch;
+ }
+
+
+ /**
+ * Constructor.
+ * @param XMLDocumentHandler The implemention of the
+ * XMLDocumentHandler operation (toXMLString, digest, ...)
+ */
+ public DTM2XNI()
+ {
+ }
+
+ /**
+ * Constructor.
+ * @param XMLDocumentHandler The implemention of the
+ * XMLDocumentHandler operation (toXMLString, digest, ...)
+ */
+ public DTM2XNI(XMLDocumentHandler handler, DTM dtm,int nodeHandle)
+ {
+ setDocumentHandler(handler);
+ setSource(dtm,nodeHandle);
+ }
+
+ /**
+ * Constructor.
+ * @param XMLDocumentHandler The implemention of the
+ * XMLDocumentHandler operation (toXMLString, digest, ...)
+ */
+ public DTM2XNI(DTM dtm,int nodeHandle)
+ {
+ setSource(dtm,nodeHandle);
+ }
+ /** Set XNI listener */
+ public void setDocumentHandler(XMLDocumentHandler handler)
+ {
+ m_XMLDocumentHandler = handler;
+ }
+
+ /** Set source to read from */
+ public void setSource(DTM dtm,int nodeHandle)
+ {
+ m_dtm=dtm;
+ m_root=nodeHandle;
+ }
+
+ /** Set wrapper context -- a vector of QNames, outermost first */
+ public void setContext(java.util.Vector context)
+ {
+ m_context=context;
+ }
+
+ /** Perform a non-recursive pre-order/post-order traversal,
+ * operating as a Visitor. startNode (preorder) and endNode
+ * (postorder) are invoked for each node as we traverse over them,
+ * with the result that the node is written out to m_XMLDocumentHandler.
+ *
+ * @param pos Nodehandle in the tree at which to start (and end) traversal --
+ * in other words, the root of the subtree to traverse over.
+ * @param context Vector of QNames to be synthesized as "wrapper" elements
+ * around this tree. It is hoped that we can phase this out when Xerces
+ * adds a context parameter to their validator.
+ * These will be tagged with an XNI annotation indicating that status, so
+ * downstream processing can strip them out again if desired.
+ *
+ * @throws TransformerException */
+ public boolean scanDocument(boolean complete) throws org.apache.xerces.xni.XNIException
+ {
+ try
+ {
+
+ int pos=m_root;
+ int top=pos;
+
+ // Document node wants to be marked as synthesized iff root wasn't
+ // a Doc.
+ Augmentations docaugs=null;
+ if(m_dtm.getNodeType(top)==DTM.DOCUMENT_NODE)
+ {
+ docaugs=m_augs;
+ docaugs.clear();
+ docaugs.putItem(DTM2XNI_ADDED_STRUCTURE,DTM2XNI_ADDED_STRUCTURE);
+ }
+
+ m_XMLDocumentHandler.startDocument(null, m_dtm.getDocumentEncoding(pos),
+ docaugs);
+
+ // Generate the synthesized context
+ // %REVIEW% Reuse one rather than recreating?
+ org.apache.xerces.xni.XMLAttributes attrs =
+ new org.apache.xerces.util.XMLAttributesImpl();
+ if(m_context!=null)
+ for(int i=0, count=m_context.size();i<count;++i)
+ {
+ // Need to convert from Xalan QName to XNI QName.
+ org.apache.xml.utils.QName q=(org.apache.xml.utils.QName) m_context.elementAt(i);
+ String ns=q.getNamespaceURI();
+ if(null!=ns && ns.length()==0) ns=null;
+ org.apache.xerces.xni.QName qq=new org.apache.xerces.xni.QName(
+ q.getPrefix(), q.getLocalPart(),q.toString(),ns);
+ // Mark as synthesized ancestor nodes
+ // NOTE: Must reassert every time; could have been altered!
+ m_augs.clear();
+ m_augs.putItem(DTM2XNI_ADDED_STRUCTURE,DTM2XNI_ADDED_STRUCTURE);
+ m_XMLDocumentHandler.startElement(qq,attrs,m_augs);
+ }
+
+ // %REVIEW% This can undoubtedly be simplified.
+ while (DTM.NULL != pos)
+ {
+ startNode(pos);
+ int nextNode = m_dtm.getFirstChild(pos);
+ while (DTM.NULL == nextNode)
+ {
+ endNode(pos);
+
+ if ((DTM.NULL != top) && top == pos)
+ break;
+
+ nextNode = m_dtm.getNextSibling(pos);
+
+ if (DTM.NULL == nextNode)
+ {
+ pos = m_dtm.getParent(pos);
+
+ if ((DTM.NULL == pos) || ((DTM.NULL != top) && (top == pos)))
+ {
+ nextNode = DTM.NULL;
+
+ break;
+ }
+ }
+ }
+
+ pos = nextNode;
+ }
+
+ // Generate the context
+ if(m_context!=null)
+ for(int i=m_context.size()-1;i>=0;--i)
+ {
+ // Need to convert from Xalan QName to XNI QName.
+ org.apache.xml.utils.QName q=(org.apache.xml.utils.QName) m_context.elementAt(i);
+ String ns=q.getNamespaceURI();
+ if(null!=ns && ns.length()==0) ns=null;
+ org.apache.xerces.xni.QName qq=new org.apache.xerces.xni.QName(
+ q.getPrefix(), q.getLocalPart(),q.toString(),ns);
+ // Mark as synthesized ancestor nodes
+ // NOTE: Must reassert every time; could have been altered!
+ m_augs.clear();
+ m_augs.putItem(DTM2XNI_ADDED_STRUCTURE,DTM2XNI_ADDED_STRUCTURE);
+ m_XMLDocumentHandler.endElement(qq,m_augs);
+ }
+
+ // Document node needs to be marked as synthesized iff root wasn't
+ // a Doc. Note that docaugs will be left null if this test didn't
+ // succeed earlier, which is what we want.
+ if(m_dtm.getNodeType(top)==DTM.DOCUMENT_NODE)
+ {
+ docaugs.clear();
+ docaugs.putItem(DTM2XNI_ADDED_STRUCTURE,DTM2XNI_ADDED_STRUCTURE);
+ }
+ m_XMLDocumentHandler.endDocument(docaugs);
+
+ return true;
+
+ }
+ catch(org.xml.sax.SAXException e)
+ {
+ throw new org.apache.xerces.xni.XNIException(e);
+ }
+ }
+
+ /** Flag indicating whether following text to be processed is raw text */
+ boolean nextIsRaw = false;
+
+ /**
+ * Partly optimized dispatch of characters from Text-style nodes.
+ *
+ * I really didn't want to propigate XNI deep into our data structures.
+ * That means pulling the data back here to process it.
+ * Best I could do was look for lighter-weight ways to retrive it...
+ * but I'm not really delighted with this solution.
+ */
+ private final void dispatchChars(int node)
+ throws org.xml.sax.SAXException
+ {
+ // Warning: getStringValue includes children, if this isn't a
+ // Text-type node.
+ XMLString value=m_dtm.getStringValue(node);
+ if(value instanceof org.apache.xpath.objects.XString)
+ {
+ // Should this be moved up to the XMLString API?
+ // I don't think we _have_ any XMLStrings other than XStrings...
+ org.apache.xml.utils.CharacterBlockEnumeration e=
+ ((org.apache.xpath.objects.XString)value).enumerateCharacterBlocks();
+
+ do
+ {
+ m_xnistring.setValues(
+ e.getChars(), e.getStart(), e.getLength());
+ m_XMLDocumentHandler.characters(m_xnistring,null);
+ }
+ while(e.nextElement()!=null);
+ }
+ else
+ {
+ // Fallback in case someone else implemented XMLString
+ // and might not support the enumeration call.
+ // Shouldn't arise, but I'm feeling paranoid this week.
+ //
+ // This may involve a lot of data recopying, which is why
+ // we prefer the enumeration -- with luck, that may be able
+ // to yield data directly from the underlying structures.
+
+ String s=value.toString();
+ char[] ch=s.toCharArray();
+ m_xnistring.setValues(ch, 0, ch.length);
+ m_XMLDocumentHandler.characters(m_xnistring,null);
+ }
+ }
+
+ /**
+ * Start processing given node
+ *
+ * %BUG% We probably need to perform namespace normalization.
+ * don't we (add declarations, add/change prefixes)... DOM's algorithm?
+ * (Adapt from Xerces DOMNormalizer.namespaceFixUp()?)
+ *
+ * @param node Node to process
+ *
+ * @throws org.xml.sax.SAXException
+ */
+ protected void startNode(int node) throws org.xml.sax.SAXException
+ {
+ switch (m_dtm.getNodeType(node))
+ {
+ case DTM.COMMENT_NODE :
+ {
+ XMLString data = m_dtm.getStringValue(node);
+
+ // This may involve a lot of data recopying, which is why
+ // we prefer the enumeration for character content...
+ // unfortunately, a single comment does need to be a single
+ // event. Might still want to try the enum first and only fall
+ // back on concatenation if that says multiple blocks exist...?
+ // %REVIEW% %OPT%
+ String s=data.toString();
+ char[] ch=s.toCharArray();
+ m_xnistring.setValues(ch, 0, ch.length);
+ m_XMLDocumentHandler.comment(m_xnistring,null);
+ }
+ break;
+ case DTM.DOCUMENT_FRAGMENT_NODE :
+ // ??;
+ break;
+ case DTM.DOCUMENT_NODE :
+ // already dealt with in traverse().
+ break;
+ case DTM.ELEMENT_NODE :
+ // %REVIEW% Reuse one rather than recreating?
+ org.apache.xerces.xni.XMLAttributes attrs =
+ new org.apache.xerces.util.XMLAttributesImpl();
+
+ // Note that this needs to scan the namespaces declared ON THIS NODE,
+ // *not* the ones inherited.
+ for (int nsn = m_dtm.getFirstNamespaceNode(node, false); DTM.NULL != nsn;
+ nsn = m_dtm.getNextNamespaceNode(node, nsn, false))
+ {
+ String nsprefix = m_dtm.getLocalName(nsn); //xmlns:whatever
+
+ m_XMLDocumentHandler.startPrefixMapping(nsprefix, m_dtm.getNodeValue(nsn),null);
+
+ // Also generate as an attr?
+ String ans = m_dtm.getNamespaceURI(nsn); // %REVIEW% Should always be NS NS.
+ org.apache.xerces.xni.QName aqq=new org.apache.xerces.xni.QName(
+ m_dtm.getPrefix(nsn), nsprefix,
+ m_dtm.getNodeName(nsn),ans);
+ int index=attrs.addAttribute(aqq,
+ "CDATA",
+ m_dtm.getNodeValue(nsn));
+ }
+
+ boolean xniTypeSeen=false;
+ for (int i = m_dtm.getFirstAttribute(node);
+ i != m_dtm.NULL;
+ i = m_dtm.getNextAttribute(i))
+ {
+ String ans = m_dtm.getNamespaceURI(i);
+ String aln=m_dtm.getLocalName(i);
+
+ // NOTE: Must reassert every time; could have been altered!
+ // %REVIEW% May be able to just pass null, if we don't wind up
+ // needing to route xsi: data through this channel.
+ m_augs.clear();
+
+ if(null!=ans && ans.length()==0)
+ ans = null; // Safety net
+ else if(XSI_NAMESPACE.equals(ans) && aln.equals("type"))
+ xniTypeSeen=true; // No need to use pass-through assertion below
+ org.apache.xerces.xni.QName aqq=new org.apache.xerces.xni.QName(
+ m_dtm.getPrefix(i), aln,
+ m_dtm.getNodeName(i),ans);
+
+ // %REVIEW% Most recent advice I've gotten from Scott is that
+ // the XPath folks do _NOT_ expect xsi:type and xsi:*schemaLocation
+ // appearing in the fragment to be honored. Very reasonably, the
+ // folks developing the Schema validator say "That's not _our_
+ // behavior"... So the only way to do this is to suppress the
+ // attributes on this end and -- presumably -- recreate them on
+ // the other end.
+ //
+ // Changing their namespace isn't sufficient; we really need to
+ // move them into a separate data channel -- eg annotations.
+ //
+ // All right, everyone, in chorus: "KLUGE!" If the user went to the
+ // trouble of building an xsi: directive into their document fragment,
+ // shouldn't we respect it? Easier _AND_ more reasonable...
+ if(SUPPRESS_XSI_ATTRIBUTES && XSI_NAMESPACE.equals(ans))
+ {
+ // %REVIEW% whether this test is necessary/sufficient
+ if("type".equals(aln) ||
+ "schemaLocation".equals(aln) ||
+ "noNamespaceSchemaLocation".equals(aln) )
+ {
+ // Side channel: Pass these as Annotation rather than
+ // Attribute (so they aren't visible to the validator),
+ // and reconstruct attrs in XNI2DTM.
+ //
+ // Architecture based on Groucho Marx's explanation
+ // of medical practice in _Horse_Feathers_
+ java.util.Vector v=(java.util.Vector)m_augs.getItem(SUPPRESSED_XSI);
+ if(v==null) v=new java.util.Vector();
+ Object[] triplet= {aqq,"CDATA",m_dtm.getNodeValue(i)};
+ v.addElement(triplet);
+ m_augs.putItem(SUPPRESSED_XSI,v);
+ continue;
+ }
+ }
+ else
+ attrs.addAttribute(aqq, "CDATA", m_dtm.getNodeValue(i));
+ }
+
+ // The business of trying to force xni:type attributes
+ // into the validation stream has been taken out of the
+ // XSLT2 spec, at least for now. I'm happy; it was a mess,
+ // even with the use of annotations to strip these out again.
+
+ String ns = m_dtm.getNamespaceURI(node);
+ if(null!=ns && ns.length()==0)
+ ns = null;
+ org.apache.xerces.xni.QName qq=new org.apache.xerces.xni.QName(
+ m_dtm.getPrefix(node), m_dtm.getLocalName(node),
+ m_dtm.getNodeName(node),ns);
+ m_XMLDocumentHandler.startElement(qq,attrs,m_augs);
+ break;
+ case DTM.PROCESSING_INSTRUCTION_NODE :
+ {
+ String name = m_dtm.getNodeName(node);
+
+ // String data = pi.getData();
+
+ // No special handling needed here; we can let the xslt-next-is-raw
+ // pass through directly rather than having to convert it.
+ // See discussion under TEXT_NODE.
+ //
+ // if (name.equals("xslt-next-is-raw"))
+ // {
+ // nextIsRaw = true;
+ // }
+ // else
+ {
+ // This may involve a lot of data recopying, which is why
+ // we prefer the enumeration for character content...
+ // unfortunately, a single comment does need to be a single
+ // event. Might still want to try the enum first and only fall
+ // back on concatenation if that says multiple blocks exist.
+ // %REVIEW% %OPT%
+ String s=m_dtm.getNodeValue(node);
+ char[] ch=s.toCharArray();
+ m_xnistring.setValues(ch, 0, ch.length);
+ m_XMLDocumentHandler.processingInstruction(name,m_xnistring,null);
+ }
+ }
+ break;
+ case DTM.CDATA_SECTION_NODE :
+ {
+ m_XMLDocumentHandler.startCDATA(null);
+ dispatchChars(node);
+ m_XMLDocumentHandler.endCDATA(null);
+ }
+ break;
+ case DTM.TEXT_NODE :
+ {
+ // No special handling needed here; we can let the xslt-next-is-raw
+ // pass through directly rather than having to convert it to a
+ // javax.xml.transform.Result.PI_DISABLE_OUTPUT_ESCAPING and
+ // javax.xml.transform.Result.PI_ENABLE_OUTPUT_ESCAPING pair, since
+ // (at this time) we do not intend to drive a serializer directly
+ // from an XNI stream. That may change in the future, though.
+ // if (nextIsRaw)
+ // {
+ // nextIsRaw = false;
+ // m_XMLDocumentHandler.processingInstruction(javax.xml.transform.Result.PI_DISABLE_OUTPUT_ESCAPING, "");
+ // dispatachChars(node);
+ // m_XMLDocumentHandler.processingInstruction(javax.xml.transform.Result.PI_ENABLE_OUTPUT_ESCAPING, "");
+ // }
+ // else
+ {
+ dispatchChars(node);
+ }
+ }
+ break;
+ case DTM.ENTITY_REFERENCE_NODE :
+ break; // Should never exist in a DTM.
+ default :
+ }
+ }
+
+ /**
+ * End processing of given node
+ *
+ *
+ * @param node Node we just finished processing
+ *
+ * @throws org.xml.sax.SAXException
+ */
+ protected void endNode(int node) throws org.xml.sax.SAXException
+ {
+
+ switch (m_dtm.getNodeType(node))
+ {
+ case DTM.DOCUMENT_NODE :
+ // Dealt with in traverse()
+ break;
+ case DTM.ELEMENT_NODE :
+ String ns = m_dtm.getNamespaceURI(node);
+ if(null!=ns && ns.length()==0)
+ ns = null;
+ org.apache.xerces.xni.QName qq=new org.apache.xerces.xni.QName(
+ m_dtm.getPrefix(node), m_dtm.getLocalName(node),
+ m_dtm.getNodeName(node),ns);
+ m_XMLDocumentHandler.endElement(qq,null);
+
+ for (int nsn = m_dtm.getFirstNamespaceNode(node, false); DTM.NULL != nsn;
+ nsn = m_dtm.getNextNamespaceNode(node, nsn, false))
+ {
+ // String prefix = m_dtm.getPrefix(nsn);
+ String prefix = m_dtm.getNodeNameX(nsn);
+ m_augs.clear();
+ m_augs.putItem(DTM2XNI_ADDED_STRUCTURE,DTM2XNI_ADDED_STRUCTURE);
+ m_XMLDocumentHandler.endPrefixMapping(prefix,m_augs);
+ }
+ break;
+ case DTM.CDATA_SECTION_NODE :
+ break;
+ case DTM.ENTITY_REFERENCE_NODE :
+ break; // Should never exist in a DTM.
+ default :
+ break;
+ }
+ }
+
+
+ // Required for compliance with XNI XMLDocumentScanner API,
+ // ignored here. I suppose we could use it to set systemID and such...
+ public void setInputSource(org.apache.xerces.xni.parser.XMLInputSource inputSource)
+ throws java.io.IOException
+ {
+ // No-op.
+ }
+} //DTM2XNI
+
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/DTM_XSequence.java b/src/org/apache/xml/dtm/ref/xni2dtm/DTM_XSequence.java
new file mode 100644
index 0000000..456d530
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/DTM_XSequence.java
@@ -0,0 +1,195 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import org.apache.xml.dtm.DTMSequence;
+
+/** This class provides an API representation for the XPath 2 Data Model's "Sequences"
+ * -- which are the basic representation for typed values. Only built-in types,
+ * types derived from built-ins, and sets thereof are returned directly by the XPath2
+ * DM; complex schema-types must be accessed through the document tree.
+ *
+ * %REVIEW% Should we have a more compact empty-sequence? (Probably not worth
+ * the effort, since XNI2DTM will use a stored instance.)
+ * */
+public class DTM_XSequence
+implements DTMSequence
+{
+ Object[] values;
+
+ // We currently expect all elements in schema-produced sequencs to have
+ // the same type. This may need to be enhanced at some point in the future.
+ XPath2Type type;
+
+ /** Create a sequence.
+ *
+ * @param value Object representation of the primitive value. May be array.
+ * @param type Datatype being represented. May be list-of type.
+ * */
+ public DTM_XSequence(Object value,XPath2Type type)
+ {
+ // If it's a list-of type, we want to unwrap that and resport
+ // the type of the individual element...
+
+ XPath2Type itemType=type.getItemType();
+
+ if(itemType==null)
+ {
+ // Creating the array is a bit wasteful. Special-case this?
+ this.values=new Object[1];
+ this.values[0]=value;
+ this.type=type;
+ }
+ else
+ {
+ this.values=(Object[])value;
+ this.type=itemType;
+ }
+ }
+
+ /** @return the number of members in this sequence. */
+ public int getLength()
+ {
+ return values.length;
+ }
+
+ /** Retrieve the value for this member of the sequence. Since values may be
+ * a heterogenous mix, and their type may not be known until they're examined,
+ * they're returned as Objects. This is storage-inefficient if the value(s)
+ * is/are builtins that map to Java primitives. Tough.
+ *
+ * @param index 0-based index into the sequence.
+ * @return the specified value
+ * @throws exception if index <0 or >=length
+ * */
+ public Object getValue(int index)
+ {
+ return values[index];
+ }
+
+ /** Retrieve the datatype namespace URI for this member of the sequence.
+ *
+ * @param index 0-based index into the sequence.
+ * @return the namespace for the specified value's type
+ * @throws exception if index <0 or >=length
+ * */
+ public String getTypeNS(int index)
+ {
+ return type.getTargetNamespace();
+ }
+
+ /** Retrieve the datatype namespace URI for this member of the sequence.
+ *
+ * %REVIEW% Do we really need type --
+ * or can we just tell folks to do instanceOf on the Java value objects?
+ *
+ * @param index 0-based index into the sequence.
+ * @return the localname of the specified value's type
+ * @throws exception if index <0 or >=length
+ * */
+ public String getTypeLocalName(int index)
+ {
+ return type.getTypeName();
+ }
+
+ /** Ask whether this member's datatype equals or is derived from a specified
+ * schema NSURI/localname pair.
+ *
+ * @param index 0-based index into the sequence.
+ * @return true if the type is an instance of this schema datatype,
+ * false if it isn't.
+ * @throws exception if index <0 or >=length
+ * */
+ public boolean isSchemaType(int index, String namespace, String localname)
+ {
+ return type.derivedFrom(namespace,localname);
+ }
+
+ /** %REVIEW% Format not yet firmly settled. Primarily for debugging purposes!
+ * */
+ public String toString()
+ {
+ StringBuffer b=new StringBuffer("Sequence[");
+ String start="";
+
+ for(int i=0;i<values.length;++i)
+ {
+ b.append(start)
+ .append(type.getTargetNamespace()).append(':').append(type.getTypeName())
+ .append(" = ");
+
+ if(values[i] instanceof int[])
+ {
+ int[] v=(int[])values[i];
+ b.append('[');
+ if(v.length>0)
+ b.append(v[0]);
+ for(int j=1;j<v.length;++j)
+ b.append(',').append(v[j]);
+ b.append(']');
+ }
+ else
+ b.append(values[i]);
+
+ if(values[i]!=null)
+ b.append(" {"+values[i].getClass().getName()+"}");
+ start=", ";
+ }
+ return b.append(']').toString();
+ }
+}
+
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/ElemImportSchema.java b/src/org/apache/xml/dtm/ref/xni2dtm/ElemImportSchema.java
new file mode 100644
index 0000000..a6b3910
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/ElemImportSchema.java
@@ -0,0 +1,87 @@
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import org.w3c.dom.Node;
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMManager;
+import org.apache.xml.dtm.ref.DTMDefaultBase;
+import org.apache.xml.dtm.ref.DTMNodeProxy;
+import org.apache.xml.dtm.ref.xni2dtm.XNI2DTM;
+import org.apache.xml.dtm.ref.xni2dtm.DTM2XNI;
+import org.apache.xpath.XPathContext;
+import javax.xml.transform.URIResolver;
+
+/** Temporary extension function, prototyping proposed XSLT2
+ * <xsl:import-schema [namespace="uri-reference"] [schema-location="uri-reference"]/>
+ *
+ * Per xslt20.30apr02.html#import-schema:
+ *
+ * The xsl:import-schema declaration is used to identify schema components (that is,
+ * definitions of types) which need to be available statically, that is, before any source
+ * document is available. Every type name used statically within the stylesheet (including
+ * type names used within XPath expressions) must be defined in an imported schema.
+ * The declaration imports the element and attribute declarations and type definitions
+ * from the schema, and maps them to types in the XPath data model according to rules
+ * defined in [].
+ *
+ * Ed. Note: Whether or not the locally declared elements and attributes of a
+ * schema are imported is an open issue.
+ *
+ * The namespace and schema-location attributes are both optional. At least one of them
+ * must be present, and it is permissible to supply both.
+ *
+ * The namespace attribute indicates that a schema for the given namespace is required
+ * by the stylesheet. This information may be enough on its own to enable an
+ * implementation to locate the required schema components.
+ *
+ * The schema-location attribute gives the URI of a location where a schema document
+ * or other resource containing the required definitions may be found. An XSLT
+ * processor must have the capability to process an XML Schema that exists at this
+ * location in the form of a source XML document; implementations may also be able to
+ * access equivalent information held in other forms, for example a compiled XML
+ * Schema, or type information expressed using some other schema language.
+ *
+ * [ERR016] It is a static error if the processor is not able to locate a schema using the
+ * namespace and/or schema-location attributes , or if the document that it locates is
+ * neither a valid XML Schema nor any other resource that the implementation can
+ * process.
+ *
+ * [ERR017] It is a static error if two xsl:import-schema declarations yield multiple
+ * definitions for the same named type, even if the definitions are consistent with each
+ * other.
+ *
+ * The use of a namespace in an xsl:import-schema declaration does not by itself make
+ * the namespace available for use in the stylesheet. If names from the namespace are
+ * used within the stylesheet, a prefix must be associated with the namespace by means
+ * of a namespace declaration, in the normal way.
+ *
+ * The precise way in which an implementation uses the namespace and/or
+ * schema-location attributes to locate schema definitions is implementation-defined.
+ *
+ * */
+public class ElemImportSchema {
+ private static final boolean JJK_DISABLE_VALIDATOR=false; // debugging hook
+
+ public static String eval(org.apache.xalan.extensions.ExpressionContext expressionContext,
+ String schemaNamespace, String schemaLocation)
+ {
+ // This happens to work in current code. It isn't really
+ // documented. Future versions expect to expose it more elegantly,
+ // according to Don Leslie. But since this extension is just
+ // temporary, let's use the cheat... We know it's going to be a
+ // particular inner class, which has an accessor to retrieve its
+ // associated XPathContext, so we reach in and ask it to reach back.
+ XPathContext xctxt = ((XPathContext.XPathExpressionContext)expressionContext).getXPathContext();
+
+ // Looking up a schema by namespace is still an ill-defined operation
+ // at best, pending the Semantic Web (which as far as I know is still
+ // naught but a vision held by Tim Berners-Lee). It will probably have
+ // to be handled by a plug-in resolver of some kind until that settles.
+ // For now, the simplest answer seems to be to make whoever does entity
+ // resolution deal with it, calling the namespace a public ID.
+ // %REVIEW%
+ xctxt.addInScopeSchemaDefinitions(schemaNamespace,schemaLocation);
+
+ return ""; // Bogus, just required because this is temporarily a function
+ }
+}
+
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/FuncData.java b/src/org/apache/xml/dtm/ref/xni2dtm/FuncData.java
new file mode 100644
index 0000000..073457f
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/FuncData.java
@@ -0,0 +1,41 @@
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMSequence;
+import org.apache.xpath.XPathContext;
+import org.w3c.dom.Node;
+
+/** Temporary extension function, prototyping proposed XPath2 xs:data()
+ * function. Returns a Java Object(which will probably become an XObject for
+ * a "non-XSLT type".
+ *
+ * This may be moved back to XSLT/XQuery, or may be folded all the way down
+ * as an operation implied by low-level expression syntax, depending on what
+ * happens in the Working Group.
+ *
+ * If the value passed in is NOT a Node, we're supposed to return the
+ * architected Error value. Currently, we assume it is a node.
+ * */
+public class FuncData {
+ private static final boolean JJK_DISABLE_VALIDATOR=false; // debugging hook
+ private static final boolean JJK_DUMMY_CODE=true; // debugging hook
+
+
+ public static DTMSequence data(org.apache.xalan.extensions.ExpressionContext context,
+ Node root)
+ {
+ // This happens to work in current code. It isn't really
+ // documented. Future versions expect to expose it more elegantly,
+ // according to Don Leslie. But since this extension is just
+ // temporary, let's use the cheat... We know it's going to be a
+ // particular inner class, which has an accessor to retrieve its
+ // associated XPathContext, so we reach in and ask it to reach back.
+ XPathContext xctxt = ((XPathContext.XPathExpressionContext)context).getXPathContext();
+
+ int sourceHandle=xctxt.getDTMHandleFromNode(root);
+ DTM sourceDTM=xctxt.getDTM(sourceHandle);
+
+ return sourceDTM.getTypedValue(sourceHandle);
+ }
+}
+
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/FuncInstanceOf.java b/src/org/apache/xml/dtm/ref/xni2dtm/FuncInstanceOf.java
new file mode 100644
index 0000000..50e217a
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/FuncInstanceOf.java
@@ -0,0 +1,63 @@
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import org.apache.xml.dtm.DTM;
+import org.apache.xpath.XPathContext;
+import org.w3c.dom.Node;
+
+/** Temporary extension function, prototyping XSLT 2.0 type matching.
+ * */
+public class FuncInstanceOf {
+ private static final boolean JJK_DISABLE_VALIDATOR=false; // debugging hook
+ private static final boolean JJK_DUMMY_CODE=true; // debugging hook
+
+
+ public static boolean eval(org.apache.xalan.extensions.ExpressionContext expressionContext,
+ Node root, String typeQName)
+ throws javax.xml.transform.TransformerException
+ {
+ // This happens to work in current code. It isn't really
+ // documented. Future versions expect to expose it more elegantly,
+ // according to Don Leslie. But since this extension is just
+ // temporary, let's use the cheat... We know it's going to be a
+ // particular inner class, which has an accessor to retrieve its
+ // associated XPathContext, so we reach in and ask it to reach back.
+ XPathContext xctxt = ((XPathContext.XPathExpressionContext)expressionContext).getXPathContext();
+
+ int sourceHandle=xctxt.getDTMHandleFromNode(root);
+ DTM sourceDTM=xctxt.getDTM(sourceHandle);
+
+ DTM2XNI d2x=new DTM2XNI(sourceDTM,sourceHandle);
+
+
+ // Need to resolve typeQName
+ org.apache.xml.utils.PrefixResolver pfxresolver=xctxt.getNamespaceContext();
+ org.apache.xml.utils.QName qn=new org.apache.xml.utils.QName(typeQName,pfxresolver);
+
+ return sourceDTM.isNodeSchemaType(
+ sourceHandle,qn.getNamespaceURI(),qn.getLocalName())
+ ;
+ }
+
+ public static boolean eval(org.apache.xalan.extensions.ExpressionContext expressionContext,
+ Node root, String typeNamespace, String typeName)
+ throws javax.xml.transform.TransformerException
+ {
+ // This happens to work in current code. It isn't really
+ // documented. Future versions expect to expose it more elegantly,
+ // according to Don Leslie. But since this extension is just
+ // temporary, let's use the cheat... We know it's going to be a
+ // particular inner class, which has an accessor to retrieve its
+ // associated XPathContext, so we reach in and ask it to reach back.
+ XPathContext xctxt = ((XPathContext.XPathExpressionContext)expressionContext).getXPathContext();
+
+ int sourceHandle=xctxt.getDTMHandleFromNode(root);
+ DTM sourceDTM=xctxt.getDTM(sourceHandle);
+
+ DTM2XNI d2x=new DTM2XNI(sourceDTM,sourceHandle);
+
+ return sourceDTM.isNodeSchemaType(
+ sourceHandle,typeNamespace,typeName)
+ ;
+ }
+}
+
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/FuncTreatAs.java b/src/org/apache/xml/dtm/ref/xni2dtm/FuncTreatAs.java
new file mode 100644
index 0000000..e218aae
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/FuncTreatAs.java
@@ -0,0 +1,75 @@
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import org.apache.xml.dtm.DTM;
+import org.apache.xpath.XPathContext;
+import org.w3c.dom.Node;
+
+/** Temporary extension function, prototyping proposed XPath2 "treat as"
+ * and "assert as" operators. Tests whether an expression is of the
+ * specified type, returning the expression's value if so and the
+ * architected Error value otherwise.
+ *
+ * There's a bunch of stuff left open in this prototype, since to do it
+ * right we need to tie in to static typing of expressions (not yet
+ * supported, and the only place where treat/assert differ), and we need
+ * typed general expressions (also not yet supported; all we have is
+ * typed nodes in the source documents or validated RTFs).
+ *
+ * I'm also not sure what the "error value" will be. For now I'm settling
+ * for announcing an error and returning null.
+ * */
+public class FuncTreatAs {
+ private static final boolean JJK_DISABLE_VALIDATOR=false; // debugging hook
+ private static final boolean JJK_DUMMY_CODE=true; // debugging hook
+
+
+ public static Node eval(org.apache.xalan.extensions.ExpressionContext expressionContext,
+ Node root, String typeQName)
+ throws javax.xml.transform.TransformerException
+ {
+ // This happens to work in current code. It isn't really
+ // documented. Future versions expect to expose it more elegantly,
+ // according to Don Leslie. But since this extension is just
+ // temporary, let's use the cheat... We know it's going to be a
+ // particular inner class, which has an accessor to retrieve its
+ // associated XPathContext, so we reach in and ask it to reach back.
+ XPathContext xctxt = ((XPathContext.XPathExpressionContext)expressionContext).getXPathContext();
+
+ int sourceHandle=xctxt.getDTMHandleFromNode(root);
+ DTM sourceDTM=xctxt.getDTM(sourceHandle);
+
+ DTM2XNI d2x=new DTM2XNI(sourceDTM,sourceHandle);
+
+
+ // Need to resolve typeQName
+ org.apache.xml.utils.PrefixResolver pfxresolver=xctxt.getNamespaceContext();
+ org.apache.xml.utils.QName qn=new org.apache.xml.utils.QName(typeQName,pfxresolver);
+
+ if(sourceDTM.isNodeSchemaType(
+ sourceHandle,qn.getNamespaceURI(),qn.getLocalName())
+ )
+ {
+ return root;
+ }
+ else
+ {
+ // %REVIEW% Should be routed to the JAXP error listener, presumably.
+ // What's the easiest way to get that from here?
+ javax.xml.transform.ErrorListener handler=xctxt.getErrorListener();
+ javax.xml.transform.TransformerException err=
+ new javax.xml.transform.TransformerException(
+ "Type assertion failed; expected "+
+ qn.getNamespaceURI()+":"+qn.getLocalName()+" but found "+
+ sourceDTM.getSchemaTypeNamespace(sourceHandle)+":"+
+ sourceDTM.getSchemaTypeName(sourceHandle) );
+ if(handler==null)
+ throw err;
+ else
+ handler.error(err);
+
+ return null; // in case handler said "proceed normally".
+ }
+ }
+
+}
+
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/FuncValidate.java b/src/org/apache/xml/dtm/ref/xni2dtm/FuncValidate.java
new file mode 100644
index 0000000..bfded98
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/FuncValidate.java
@@ -0,0 +1,185 @@
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import org.w3c.dom.Node;
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMManager;
+import org.apache.xml.dtm.ref.DTMDefaultBase;
+import org.apache.xml.dtm.ref.DTMNodeProxy;
+import org.apache.xml.dtm.ref.xni2dtm.XNI2DTM;
+import org.apache.xml.dtm.ref.xni2dtm.DTM2XNI;
+import org.apache.xpath.XPathContext;
+
+/** Temporary extension function, prototyping proposed XPath2 FuncValidate.
+ *
+ * This may be moved back to XSLT/XQuery, or may be folded all the way down
+ * as an operation implied by low-level expression syntax, depending on what
+ * happens in the Working Group.
+ *
+ * %REVIEW% Current code validates only a single root element. If we want more,
+ * we can do it but it'll take a bit more coding.
+ * */
+public class FuncValidate {
+ private static final boolean JJK_DISABLE_VALIDATOR=false; // debugging hook
+ private static final boolean JJK_DUMMY_CODE=true; // debugging hook
+
+
+ public static Node eval(org.apache.xalan.extensions.ExpressionContext context,
+ Node root)
+ {
+ return eval(context,root,null);
+ }
+ public static Node eval(org.apache.xalan.extensions.ExpressionContext expressionContext,
+ Node root, String contextPath)
+ {
+ // This happens to work in current code. It isn't really
+ // documented. Future versions expect to expose it more elegantly,
+ // according to Don Leslie. But since this extension is just
+ // temporary, let's use the cheat... We know it's going to be a
+ // particular inner class, which has an accessor to retrieve its
+ // associated XPathContext, so we reach in and ask it to reach back.
+ XPathContext xctxt = ((XPathContext.XPathExpressionContext)expressionContext).getXPathContext();
+
+ int sourceHandle=xctxt.getDTMHandleFromNode(root);
+ DTM sourceDTM=xctxt.getDTM(sourceHandle);
+
+ DTM2XNI d2x=new DTM2XNI(sourceDTM,sourceHandle);
+
+ // %REVIEW% Still need to do something with contextPath.
+ // d2x is set up to synthesize a wrapper and then discard it again --
+ // BUT this fails when one of the synthesized elements has attr requirements,
+ // as Xerces apparently optimizes by not validating kids if the start-tag
+ // isn't valid.
+ //
+ // A better answer would be to set the validator's context;
+ // Xerces agrees that this is a desirable feature but may not have
+ // implemented it yet.
+ if(contextPath!=null)
+ {
+ java.util.Vector d2xContext=new java.util.Vector();
+ // xctxt not available to extensions?
+ org.apache.xml.utils.PrefixResolver pfxresolver=xctxt.getNamespaceContext();
+
+ java.util.StringTokenizer e=new java.util.StringTokenizer(contextPath,"/");
+ while(e.hasMoreElements())
+ {
+ String name=(String)e.nextElement();
+ org.apache.xml.utils.QName qn=new org.apache.xml.utils.QName(name,pfxresolver);
+ d2xContext.addElement(qn);
+ }
+ d2x.setContext(d2xContext);
+ }
+
+ // VALIDATION GOES HERE!
+ // Sandy Gao recommends "create a customized parser configuration,
+ // which contains an XNI event source, a validator, and (optionally)
+ // a document handler." See "pipelines" in the XNI docs.
+ // I don't really grok that yet, so this is a SWAG based on what
+ // Elena Litani did for the DOM revalidator.
+ //
+ // If we need to suppress explicit xsi:*schemaLocation directives, recommended
+ // kluge is to install a entity-resolver into the pipe which delivered
+ // a schema with appropriate targetNamespae and no details (or just empty???)
+ //
+ // If we need to suppress explicit xsi:type directives -- Xerces developers
+ // agree with me that this is Inherently Stupid. Solution would be to pass
+ // those through a secondary channel, eg by turning them into custom
+ // annotations until they get back to XNI.
+ XNISource xsrc;
+ if(JJK_DISABLE_VALIDATOR)
+ xsrc=new XNISource(d2x,null); // Test: Just flow thru
+ else
+ {
+ // ISSUE: Do we need to explicitly normalize namespaces?
+
+ /* Adapted from Xerces DOMRevalidator.
+ Probably shouldn't be using this class, but
+ I haven't yet gotten the Xerces team to give me
+ a real stand-alone example I could model this on.
+
+ I'm also REALLY not convinced this is a typical XNI setup;
+ I'm surprised I have to muck directly with the validator
+ rather than setting up a configuration that encapsulates
+ the dataflow more completely. (On the other hand, I'm also
+ surpised that Configuration doesn't seem to implement
+ DocumentSource.
+ */
+ DOMValidationConfigurationSwipedFromXerces xnipipe
+ =new DOMValidationConfigurationSwipedFromXerces(null);
+ xnipipe.setFeature(DOMValidationConfigurationSwipedFromXerces.VALIDATION,true);
+ xnipipe.setFeature(DOMValidationConfigurationSwipedFromXerces.SCHEMA,true);
+ org.apache.xerces.impl.xs.XMLSchemaValidator validator
+ =new org.apache.xerces.impl.xs.XMLSchemaValidator();
+ xnipipe.addComponent(validator); // so config's reset() hits it
+
+ if(JJK_DUMMY_CODE)
+ {
+ /* %REVIEW% Code in this section is preliminary/bogus,
+ for debugging only */
+
+ /* %ISSUE% 1) Is there such a thing as a base URI for this fragment?
+ %BUG% It is very unclear that this fragment has a real base URI.
+ Also, note that this call fails for RTFDTMs.
+
+ (We may in fact need to set this otherwise to prevent
+ xsi:schemaLocation from succeeding, unless we can tell
+ Xerces not to honor that directive.. or filter it out
+ in DTM2XNI, ugh. For now leave this unset to expose
+ failure to reference the explicitly loaded GrammarPool.)
+ */
+ //validator.setBaseURI(sourceDTM.getDocumentBaseURI());
+
+ /* %ISSUE% 2) Do we need to track mid-stream changes by issuing
+ entity/locator information into the stream?
+ %BUG% It is very unclear that this fragment has a real base URI.
+ Also, we don't actually record that data node-by-node unless
+ tooling support is turned on... and even then I'm not sure
+ this is retained after a layer or two of RTFs.
+ */
+ // No.
+
+ /* %ISSUE% 3) XPath2 says schema location comes from the XPath context,
+ *not* from the document. Need to assert this via the
+ schemaLocation property, or preparse into a Grammar Pool
+ and use that. (I expect the latter since other parts of
+ XPath2/XQuery/XSLT2 also want to muck with schemas.)
+
+ %TODO%: Need to add that to the XPathContext and
+ Xalan startup?
+ */
+ // Experimental, force it in manually just to see what happens
+ xnipipe.setProperty(xnipipe.GRAMMAR_POOL,
+ xctxt.getInScopeSchemaDefinitions().getGrammarPool());
+
+ /* %ISSUE% 5) NOTE that we're making no effort to retain existing
+ type info (per latest XPath data I've seen). If we were,
+ we get into ugly issues w/r/t having to retain type on
+ Literal Result Elements in the stylesheet, plus questions
+ about what (if anything) happens when an LRE has
+ an xsi:type. The XQUERY team is still flailing on this topic.
+ */
+ }
+
+
+ d2x.setDocumentHandler(validator);
+
+ // Wrap up the pipeline for our use.
+ // There ought to be a way to avoid passing all these parts...
+ xsrc=new XNISource(d2x,xnipipe,validator,null);
+ }
+
+ // %REVIEW% %BUG%
+ // I don't think we can make this incremental, attractive
+ // as that thought might be -- the source DTM might be an RTF and
+ // might Go Away. We probably _should_ make it an RTF DTM, but those
+ // currently aren't supported for XNI.
+ DTM newDTM=xctxt.getDTM(xsrc,
+ true, // unique
+ null, // whitespace filter
+ false, // incremental -- not supported at this writing
+ false // doIndexing -- open to debate
+ );
+
+ return newDTM.getNode(newDTM.getDocument());
+ }
+}
+
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/NamespaceSupportAtDTMNode.java b/src/org/apache/xml/dtm/ref/xni2dtm/NamespaceSupportAtDTMNode.java
new file mode 100644
index 0000000..22acb46
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/NamespaceSupportAtDTMNode.java
@@ -0,0 +1,322 @@
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import org.xml.sax.helpers.NamespaceSupport;
+import java.util.Enumeration;
+import org.apache.xml.dtm.*;
+
+
+/** Perform SAX-style lookup of namespace information in the context of a
+ * DTM node. Written as part of the glue for XNI2DTM and XPath2Type, but
+ * may be useful elsewhere. Unclear which package it should live in.
+ * */
+public class NamespaceSupportAtDTMNode extends NamespaceSupport {
+ DTM m_dtm;
+ int m_nodeHandle;
+
+ /**
+ * Constructor for NamespaceContextAtDTMNode
+ */
+ public NamespaceSupportAtDTMNode() {
+ throw new UnsupportedOperationException("not supported in this class");
+ }
+
+ /**
+ * Constructor for NamespaceContextAtDTMNode
+ */
+ public NamespaceSupportAtDTMNode(DTM dtm,int nodeHandle) {
+ m_dtm=dtm;
+ m_nodeHandle=nodeHandle;
+ }
+
+ public boolean declarePrefix (String prefix, String uri) {
+ throw new UnsupportedOperationException("not supported in this class");
+ }
+ /* No-op in this instantiation */
+ public void pushContext ()
+ {
+ }
+ /* No-op in this instantiation */
+ public void popContext ()
+ {
+ }
+ /* No-op in this instantiation */
+ public void reset ()
+ {
+ }
+
+ /**
+ * Return an enumeration of all prefixes declared in this context.
+ *
+ * <p>The empty (default) prefix will be included in this
+ * enumeration; note that this behaviour differs from that of
+ * {@link #getPrefix} and {@link #getPrefixes}.</p>
+ *
+ * @return An enumeration of all prefixes declared in this
+ * context.
+ * @see #getPrefixes
+ * @see #getURI
+ */
+ public Enumeration getDeclaredPrefixes ()
+ {
+ return new Enumeration()
+ {
+ int nshandle=m_dtm.getFirstNamespaceNode(
+ m_nodeHandle,true);
+
+ public boolean hasMoreElements()
+ {
+ return nshandle!=DTM.NULL;
+ }
+ public Object nextElement()
+ {
+ if(nshandle==DTM.NULL)
+ return null;
+ String prefix=m_dtm.getLocalName(nshandle);
+ nshandle=m_dtm.getNextNamespaceNode(
+ m_nodeHandle,nshandle,true);
+ return prefix;
+ }
+ };
+ }
+
+
+ /**
+ * Return one of the prefixes mapped to a Namespace URI.
+ *
+ * <p>If more than one prefix is currently mapped to the same
+ * URI, this method will make an arbitrary selection; if you
+ * want all of the prefixes, use the {@link #getPrefixes}
+ * method instead.</p>
+ *
+ * <p><strong>Note:</strong> this will never return the empty (default) prefix;
+ * to check for a default prefix, use the {@link #getURI getURI}
+ * method with an argument of "".</p>
+ *
+ * @param uri The Namespace URI.
+ * @param isAttribute true if this prefix is for an attribute
+ * (and the default Namespace is not allowed).
+ * @return One of the prefixes currently mapped to the URI supplied,
+ * or null if none is mapped or if the URI is assigned to
+ * the default Namespace.
+ * @see #getPrefixes(java.lang.String)
+ * @see #getURI
+ */
+ public String getPrefix (String uri)
+ {
+ if(uri==null)
+ uri="";
+
+ int nshandle=m_dtm.getFirstNamespaceNode(
+ m_nodeHandle,true);
+ while(nshandle!=DTM.NULL)
+ {
+ if(uri.equals(m_dtm.getNamespaceURI(nshandle)))
+ {
+ String prefix=m_dtm.getLocalName(nshandle);
+ if(prefix!=null && !prefix.equals(""))
+ return prefix;
+ }
+ nshandle=m_dtm.getNextNamespaceNode(
+ m_nodeHandle,nshandle,true);
+ }
+ return null;
+ }
+
+ /**
+ * Look up a prefix and get the currently-mapped Namespace URI.
+ *
+ * <p>This method looks up the prefix in the current context.
+ * Use the empty string ("") for the default Namespace.</p>
+ *
+ * @param prefix The prefix to look up.
+ * @return The associated Namespace URI, or null if the prefix
+ * is undeclared in this context.
+ * @see #getPrefix
+ * @see #getPrefixes
+ */
+ public String getURI (String prefix)
+ {
+ if(prefix==null)
+ prefix="";
+
+ int nshandle=m_dtm.getFirstNamespaceNode(
+ m_nodeHandle,true);
+ while(nshandle!=DTM.NULL)
+ {
+ if(prefix.equals(m_dtm.getLocalName(nshandle))) // getPrefix?
+ //return m_dtm.getNamespaceURI(nshandle);
+ return m_dtm.getNodeValue(nshandle);
+ nshandle=m_dtm.getNextNamespaceNode(
+ m_nodeHandle,nshandle,true);
+ }
+ return null;
+ }
+
+ /**
+ * Return an enumeration of all prefixes currently declared.
+ *
+ * <p><strong>Note:</strong> if there is a default prefix, it will not be
+ * returned in this enumeration; check for the default prefix
+ * using the {@link #getURI getURI} with an argument of "".</p>
+ *
+ * @return An enumeration of all prefixes declared in the
+ * current context except for the empty (default)
+ * prefix.
+ * @see #getDeclaredPrefixes
+ * @see #getURI
+ */
+ public Enumeration getPrefixes ()
+ {
+ return new Enumeration()
+ {
+ int nshandle=m_dtm.getFirstNamespaceNode(
+ m_nodeHandle,true);
+
+ public boolean hasMoreElements()
+ {
+ skipdefault();
+ return nshandle!=DTM.NULL;
+ }
+ public Object nextElement()
+ {
+ skipdefault();
+ if(nshandle==DTM.NULL)
+ return null;
+ String prefix=m_dtm.getLocalName(nshandle);
+ nshandle=m_dtm.getNextNamespaceNode(
+ m_nodeHandle,nshandle,true);
+ return prefix;
+ }
+
+ private void skipdefault()
+ {
+ if(nshandle!=DTM.NULL &&
+ "".equals(m_dtm.getLocalName(nshandle)))
+ nshandle=m_dtm.getNextNamespaceNode(
+ m_nodeHandle,nshandle,true);
+ }
+ };
+ }
+
+ /**
+ * Return an enumeration of all prefixes currently declared for a URI.
+ *
+ * <p>This method returns prefixes mapped to a specific Namespace
+ * URI. The xml: prefix will be included. If you want only one
+ * prefix that's mapped to the Namespace URI, and you don't care
+ * which one you get, use the {@link #getPrefix getPrefix}
+ * method instead.</p>
+ *
+ * <p><strong>Note:</strong> the empty (default) prefix is <em>never</em> included
+ * in this enumeration; to check for the presence of a default
+ * Namespace, use the {@link #getURI getURI} method with an
+ * argument of "".</p>
+ *
+ * @param uri The Namespace URI.
+ * @return An enumeration of all prefixes declared in the
+ * current context.
+ * @see #getPrefix
+ * @see #getDeclaredPrefixes
+ * @see #getURI
+ */
+ public Enumeration getPrefixes (String uri)
+ {
+ return new Enumeration()
+ {
+ String e_uri;
+ int nshandle=m_dtm.getFirstNamespaceNode(
+ m_nodeHandle,true);
+
+ // Kluge to pass in the URI
+ public Enumeration setURI(String uri)
+ {
+ e_uri=uri;
+ return this;
+ }
+
+ public boolean hasMoreElements()
+ {
+ skipwronguri();
+ return nshandle!=DTM.NULL;
+ }
+ public Object nextElement()
+ {
+ skipwronguri();
+ if(nshandle==DTM.NULL)
+ return null;
+ String prefix=m_dtm.getLocalName(nshandle);
+ nshandle=m_dtm.getNextNamespaceNode(
+ m_nodeHandle,nshandle,true);
+ return prefix;
+ }
+
+ private void skipwronguri()
+ {
+ while(nshandle!=DTM.NULL &&
+ ! (e_uri.equals(m_dtm.getLocalName(nshandle))) )
+ nshandle=m_dtm.getNextNamespaceNode(
+ m_nodeHandle,nshandle,true);
+ }
+ }.setURI(uri);
+ }
+
+
+ /**
+ * Process a raw XML 1.0 name, after all declarations in the current
+ * context have been handled by {@link #declarePrefix declarePrefix()}.
+ *
+ * <p>This method processes a raw XML 1.0 name in the current
+ * context by removing the prefix and looking it up among the
+ * prefixes currently declared. The return value will be the
+ * array supplied by the caller, filled in as follows:</p>
+ *
+ * <dl>
+ * <dt>parts[0]</dt>
+ * <dd>The Namespace URI, or an empty string if none is
+ * in use.</dd>
+ * <dt>parts[1]</dt>
+ * <dd>The local name (without prefix).</dd>
+ * <dt>parts[2]</dt>
+ * <dd>The original raw name.</dd>
+ * </dl>
+ *
+ * <p>All of the strings in the array will be internalized. If
+ * the raw name has a prefix that has not been declared, then
+ * the return value will be null.</p>
+ *
+ * <p>Note that attribute names are processed differently than
+ * element names: an unprefixed element name will received the
+ * default Namespace (if any), while an unprefixed attribute name
+ * will not.</p>
+ *
+ * @param qName The raw XML 1.0 name to be processed.
+ * @param parts An array supplied by the caller, capable of
+ * holding at least three members.
+ * @param isAttribute A flag indicating whether this is an
+ * attribute name (true) or an element name (false).
+ * @return The supplied array holding three internalized strings
+ * representing the Namespace URI (or empty string), the
+ * local name, and the raw XML 1.0 name; or null if there
+ * is an undeclared prefix.
+ * @see #declarePrefix
+ * @see java.lang.String#intern */
+ public String [] processName (String qName, String parts[],
+ boolean isAttribute)
+ {
+ parts[2]=qName;
+
+ int colon=qName.indexOf(':');
+ parts[1]=(colon<0) ? qName : qName.substring(colon+1);
+
+ String pfx;
+ if(colon==-1)
+ pfx=(isAttribute) ? null : "";
+ else
+ pfx=qName.substring(0,colon);
+ parts[0] = (pfx==null) ? null : getURI(pfx);
+
+ return parts;
+ }
+
+}
+
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/XNI2DTM.java b/src/org/apache/xml/dtm/ref/xni2dtm/XNI2DTM.java
new file mode 100644
index 0000000..b7f1c06
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/XNI2DTM.java
@@ -0,0 +1,1757 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import javax.xml.transform.Source;
+
+import org.apache.xerces.impl.xs.AttributePSVImpl;
+import org.apache.xerces.impl.xs.ElementPSVImpl;
+import org.apache.xerces.impl.xs.psvi.XSSimpleTypeDefinition;
+import org.apache.xerces.impl.xs.psvi.XSTypeDefinition;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLAttributes;
+import org.apache.xerces.xni.XMLDTDHandler;
+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.XMLErrorHandler;
+import org.apache.xerces.xni.parser.XMLParseException;
+import org.apache.xerces.xni.parser.XMLPullParserConfiguration;
+import org.apache.xerces.xni.psvi.ItemPSVI;
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMManager;
+import org.apache.xml.dtm.DTMSequence;
+import org.apache.xml.dtm.DTMWSFilter;
+import org.apache.xml.utils.SparseVector;
+import org.apache.xml.utils.WrappedRuntimeException;
+import org.apache.xpath.objects.XSequence;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * This class implements a DTM that is constructed via an XNI data stream.
+ *
+ * Please note that it this is a PROTOTYPE, since the Xerces post-schema
+ * validation infoset (PSVI) APIs it is using are themselves prototypes and
+ * subject to change without warning. The most recent such change was from
+ * "lightweight" to "heavyweight" schema models -- the former are no longer
+ * supported.
+ *
+ * This version is derived from SAX2DTM for ease of implementation and
+ * support, but deliberately blocks external access to
+ * the SAX-listener calls to make our testing a bit more rigorous.
+ *
+ * Note to developers: Both XNI and Xalan have classes called XMLString.
+ * Don't confuse them!
+ *
+ * %REVIEW% Should we re-unify this with SAX2(RTF)DTM?
+ * (Since we'll want to create typed temporary trees, definitely an issue...)
+ * To actually _USE_ as a temporary tree, we'd need to accept SAX
+ * rather than blocking it, and/or rewrite Xalan core to be XNI-based,
+ * and/or do some bypassing to add types to SAX stream.
+ * Test confirms we can successfully derive from either.
+ */
+public class XNI2DTM
+ extends org.apache.xml.dtm.ref.sax2dtm.SAX2DTM
+ implements XMLDocumentHandler, XMLErrorHandler, XMLDTDHandler
+{
+ /** DEBUGGING FLAG: Set true to monitor XNI events and similar diagnostic info. */
+ private static final boolean DEBUG = false;
+
+ /** %OPT% %REVIEW% PROTOTYPE: Schema Type information, datatype as instantiated.
+ * See discussion in addNode */
+ protected SparseVector m_schemaTypeOverride=new SparseVector();
+
+ /**
+ * If we're building the model incrementally on demand, we need to
+ * be able to tell the source when to send us more data.
+ *
+ * Note that if this has not been set, and you attempt to read ahead
+ * of the current build point, we'll probably throw a null-pointer
+ * exception. We could try to wait-and-retry instead, as a very poor
+ * fallback, but that has all the known problems with multithreading
+ * on multiprocessors and we Don't Want to Go There.
+ *
+ * @see setIncrementalXNISource
+ */
+ private XMLPullParserConfiguration m_incrementalXNISource = null;
+
+ /** The XNI Document locator
+ * %REVIEW% Should we be storing a SAX locator instead? */
+ transient private LocatorWrapper m_locator_wrapper = new LocatorWrapper();
+
+ /** Manefest constant: Schema namespace string */
+ private static final String SCHEMANS="http://www.w3.org/2001/XMLSchema";
+
+ /** Manefest constant: Message for SAX-disablement stubs */
+ static final String UNEXPECTED="XNI2DTM UNEXPECTED SAX ";
+
+ /**
+ * Construct a XNI2DTM object ready to be constructed from XNI
+ * ContentHandler events.
+ *
+ * @param mgr The DTMManager who owns this DTM.
+ * @param source the JAXP 1.1 Source object for this DTM.
+ * @param dtmIdentity The DTM identity ID for this DTM.
+ * @param whiteSpaceFilter The white space filter for this DTM, which may
+ * be null.
+ * @param xstringfactory XMLString factory for creating character content.
+ * @param doIndexing true if the caller considers it worth it to use
+ * indexing schemes.
+ */
+ public XNI2DTM(DTMManager mgr, Source source, int dtmIdentity,
+ DTMWSFilter whiteSpaceFilter,
+ org.apache.xml.utils.XMLStringFactory xstringfactory,
+ boolean doIndexing)
+ {
+ super(mgr, source, dtmIdentity, whiteSpaceFilter,
+ xstringfactory, doIndexing);
+ }
+
+
+ /** ADDED for XNI, SUPPLEMENTS non-schema-typed addNode:
+ *
+ * Construct the node map from the node. EXTENDED to carry PSVI type data
+ * delivered via XNI. This is currently using non-published Xerces APIs, which
+ * are subject to change as their PSVI support becomes more official.
+ *
+ * @param type raw type ID, one of DTM.XXX_NODE.
+ * @param expandedTypeID The expended type ID.
+ * @param parentIndex The current parent index.
+ * @param previousSibling The previous sibling index.
+ * @param dataOrPrefix index into m_data table, or string handle.
+ * @param canHaveFirstChild true if the node can have a first child, false
+ * if it is atomic.
+ * @param actualType Schema type object as resolved in actual instance document
+ *
+ * @return The index identity of the node that was added.
+ */
+ protected int addNode(int type, int expandedTypeID,
+ int parentIndex, int previousSibling,
+ int dataOrPrefix, boolean canHaveFirstChild,
+ XPath2Type actualType)
+ {
+ int identity=super.addNode(type,expandedTypeID,
+ parentIndex,previousSibling,
+ dataOrPrefix,canHaveFirstChild);
+
+ // The goal is to not consume storage for types unless they actualy exist,
+ // and to minimize per-node overhead.
+ //
+ // NOTE: Record first-seen as default even if it is null, because
+ // otherwise late changes of type will bash previously recorded
+ // nodes. This is NOT necessarily maximally efficient, but to really
+ // optimize we would have to rewrite data to make the default the most
+ // common -- and since Scott insists that overrides will be uncommon,
+ // I don't want to go there.
+ //
+ // NOTE: Element schema-types aren't fully resolved until endElement, and
+ // need to be dealt with there.
+ if(type!=ELEMENT_NODE)
+ {
+ // Try to record as default for this nodetype
+ if(!m_expandedNameTable.setSchemaType(m_exptype.elementAt(identity),
+ actualType)
+ )
+ {
+ m_schemaTypeOverride.setElementAt(actualType,identity);
+ }
+ }
+
+ return identity;
+ }
+
+ /** ADDED FOR XPATH2: Query schema type name of a given node.
+ *
+ * %REVIEW% Is this actually needed?
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return null if no type known, else returns the expanded-QName (namespace URI
+ * rather than prefix) of the type actually
+ * resolved in the instance document. Note that this may be derived from,
+ * rather than identical to, the type declared in the schema.
+ */
+ public String getSchemaTypeName(int nodeHandle)
+ {
+ int identity=makeNodeIdentity(nodeHandle);
+
+ if(identity!=DTM.NULL)
+ {
+ XPath2Type actualType=(XPath2Type)m_schemaTypeOverride.elementAt(identity);
+ if(actualType==null)
+ actualType=(XPath2Type)m_expandedNameTable.getSchemaType(m_exptype.elementAt(identity));
+
+ if(actualType!=null)
+ {
+ String nsuri=actualType.getTargetNamespace();
+ String local=actualType.getTypeName();
+ return (nsuri==null)
+ ? local
+ : nsuri+":"+local;
+ }
+ }
+
+ return null;
+ }
+
+ /** ADDED FOR XPATH2: Query schema type namespace of a given node.
+ *
+ * %REVIEW% Is this actually needed?
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return null if no type known, else returns the namespace URI
+ * of the type actually resolved in the instance document. This may
+ * be null if the default/unspecified namespace was used.
+ * Note that this may be derived from,
+ * rather than identical to, the type declared in the schema.
+ */
+ public String getSchemaTypeNamespace(int nodeHandle)
+ {
+ int identity=makeNodeIdentity(nodeHandle);
+
+ if(identity!=DTM.NULL)
+ {
+ XPath2Type actualType=(XPath2Type)m_schemaTypeOverride.elementAt(identity);
+ if(actualType==null)
+ actualType=(XPath2Type)m_expandedNameTable.getSchemaType(m_exptype.elementAt(identity));
+ if(actualType!=null)
+ {
+ return actualType.getTargetNamespace();
+ }
+ }
+
+ return null;
+ }
+
+ /** ADDED FOR XPATH2: Query schema type localname of a given node.
+ *
+ * %REVIEW% Is this actually needed?
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @return null if no type known, else returns the localname of the type
+ * resolved in the instance document. Note that this may be derived from,
+ * rather than identical to, the type declared in the schema.
+ */
+ public String getSchemaTypeLocalName(int nodeHandle)
+ {
+ int identity=makeNodeIdentity(nodeHandle);
+
+ if(identity!=DTM.NULL)
+ {
+ XPath2Type actualType=(XPath2Type)m_schemaTypeOverride.elementAt(identity);
+ if(actualType==null)
+ actualType=(XPath2Type)m_expandedNameTable.getSchemaType(m_exptype.elementAt(identity));
+ if(actualType!=null)
+ {
+ return actualType.getTypeName();
+ }
+ }
+
+ return null;
+ }
+
+ /** ADDED FOR XPATH2: Query whether node's type is derived from a specific type
+ *
+ * @param nodeHandle DTM Node Handle of Node to be queried
+ * @param namespace String containing URI of namespace for the type we're intersted in
+ * @param localname String containing local name for the type we're intersted in
+ * @return true if node has a Schema Type which equals or is derived from
+ * the specified type. False if the node has no type or that type is not
+ * derived from the specified type.
+ */
+ public boolean isNodeSchemaType(int nodeHandle, String namespace, String localname)
+ {
+ int identity=makeNodeIdentity(nodeHandle);
+
+ if(identity!=DTM.NULL)
+ {
+ XPath2Type actualType=(XPath2Type)m_schemaTypeOverride.elementAt(identity);
+ if(actualType==null)
+ actualType=(XPath2Type)m_expandedNameTable.getSchemaType(m_exptype.elementAt(identity));
+ if(actualType!=null)
+ return actualType.derivedFrom(namespace,localname);
+ }
+
+ return false;
+ }
+
+ /** ADDED FOR XPATH2: Retrieve the typed value(s), based on the schema type
+ *
+ * %REVIEW% That may not be
+ * */
+ public DTMSequence getTypedValue(int nodeHandle)
+ {
+ // Determine whether instance of built-in type, or list thereof
+ // If so, map to corresponding Java type
+ // Retrieve string content (as always, for element this spans children
+ // If type was xs:string (or untyped?) just return that in a collection.
+ // Else parse into collection object, return that
+
+ int identity=makeNodeIdentity(nodeHandle);
+ if(identity==DTM.NULL)
+ return DTMSequence.EMPTY;
+
+ XPath2Type actualType=(XPath2Type)m_schemaTypeOverride.elementAt(identity);
+ if(actualType==null)
+ actualType=(XPath2Type)m_expandedNameTable.getSchemaType(m_exptype.elementAt(identity));
+
+ if(actualType==null)
+ return DTMSequence.EMPTY;
+
+ /* %REVIEW% Efficiency issues; value may be in FSB or scattered,
+ in which case generating a Java String may arguably be wasteful.
+ And are we handling list types at all reasonably?
+ */
+ //GONK lists;
+ //GONK efficiency;
+
+ // Gathers all text. Is that right? Should we not do if type is not known?
+ String textvalue=getStringValue(nodeHandle).toString();
+
+ // DTM node should provide the namespace context.
+ // Do we have an existing encapulation for that concept?
+
+ return actualType.typedValue(textvalue,
+ new org.apache.xml.dtm.ref.xni2dtm.NamespaceSupportAtDTMNode(this,nodeHandle));
+ }
+
+
+ //===========================================================================
+
+ /** OVERRIDDEN FOR XNI:
+ *
+ * Ask the CoRoutine parser to terminate and clear the reference. If
+ * the parser has already been cleared, this will have no effect.
+ *
+ * @param callDoTerminate true if parsing should be terminated
+ */
+ public void clearCoRoutine(boolean callDoTerminate)
+ {
+
+ if (null != m_incrementalXNISource)
+ {
+ if (callDoTerminate)
+ m_incrementalXNISource.cleanup();
+
+ m_incrementalXNISource = null;
+ }
+ }
+
+ /** ADDED FOR XNI, REPLACES setIncrementalSAXSource:
+ *
+ * Bind a IncrementalXNISource to this DTM. If we discover we need nodes
+ * that have not yet been built, we will ask this object to send us more
+ * events, and it will manage interactions with its data sources.
+ *
+ * Note that we do not actually build the IncrementalXNISource, since we don't
+ * know what source it's reading from, what thread that source will run in,
+ * or when it will run.
+ *
+ * @param incrementalXNISource The parser that we want to recieve events from
+ * on demand.
+ * @param appCoRID The CoRoutine ID for the application.
+ */
+ public void setIncrementalXNISource(XMLPullParserConfiguration incrementalXNISource)
+ {
+
+ // Establish coroutine link so we can request more data
+ //
+ // Note: It's possible that some versions of IncrementalXNISource may
+ // not actually use a CoroutineManager, and hence may not require
+ // that we obtain an Application Coroutine ID. (This relies on the
+ // coroutine transaction details having been encapsulated in the
+ // IncrementalXNISource.do...() methods.)
+ m_incrementalXNISource = incrementalXNISource;
+
+ // Establish XNI-stream link so we can receive the requested data
+ incrementalXNISource.setDocumentHandler(this);
+
+ // Are the following really needed? incrementalXNISource doesn't yet
+ // support them, and they're mostly no-ops here...
+ incrementalXNISource.setErrorHandler(this);
+ incrementalXNISource.setDTDHandler(this);
+ }
+
+ /** DISABLED FOR XNI:
+ *
+ * getContentHandler returns "our SAX builder" -- the thing that
+ * someone else should send SAX events to in order to extend this
+ * DTM model.
+ *
+ * %REVIEW% We _could_ leave SAX support in place and have a single model
+ * that handles both kinds of event streams. I've chosen to block it
+ * during development for better isolation of XNI support.
+ *
+ * @return null since this model doesn't respond to SAX events
+ */
+ public org.xml.sax.ContentHandler getContentHandler()
+ {
+ return null;
+ }
+
+ /**
+ * Return this DTM's lexical handler.
+ *
+ * %REVIEW% Should this return null if constrution already done/begun?
+ *
+ * %REVIEW% We _could_ leave SAX support in place and have a single model
+ * that handles both kinds of event streams. I've chosen to block it
+ * during development for better isolation of XNI support.
+ *
+ * @return null since this model doesn't respond to SAX events
+ */
+ public org.xml.sax.ext.LexicalHandler getLexicalHandler()
+ {
+ return null;
+ }
+
+ /**
+ * Return this DTM's DTDHandler.
+ *
+ * %REVIEW% We _could_ leave SAX support in place and have a single model
+ * that handles both kinds of event streams. I've chosen to block it
+ * during development for better isolation of XNI support.
+ *
+ * @return null since this model doesn't respond to SAX events
+ */
+ public org.xml.sax.DTDHandler getDTDHandler()
+ {
+ return null;
+ }
+
+ /**
+ * Return this DTM's ErrorHandler.
+ *
+ * @return null if this model doesn't respond to SAX error events.
+ */
+ public org.xml.sax.ErrorHandler getErrorHandler()
+ {
+ //return this;
+ return null;
+ }
+
+ /**
+ * Return this DTM's DeclHandler.
+ *
+ * @return null if this model doesn't respond to SAX Decl events.
+ */
+ public org.xml.sax.ext.DeclHandler getDeclHandler()
+ {
+ //return this;
+ return null;
+ }
+
+ /** OVERRIDDEN FOR XNI:
+ *
+ * @return true iff we're building this model incrementally (eg
+ * we're partnered with a IncrementalXNISource) and thus require that the
+ * transformation and the parse run simultaneously. Guidance to the
+ * DTMManager.
+ */
+ public boolean needsTwoThreads()
+ {
+ return null != m_incrementalXNISource;
+ }
+
+ /** OVERRIDDEN FOR XNI:
+ *
+ * This method should try and build one or more nodes in the table.
+ *
+ * %REVIEW% Is it worth factoring out the actual request for more events
+ * into a subroutine, isolating it better? Consider if/when we re-merge
+ * with SAX2DTM.
+ *
+ * @return The true if a next node is found or false if
+ * there are no more nodes.
+ */
+ protected boolean nextNode()
+ {
+
+ if (null == m_incrementalXNISource)
+ return false;
+
+ if (m_endDocumentOccured)
+ {
+ clearCoRoutine();
+
+ return false;
+ }
+
+ try
+ {
+ boolean gotMore = m_incrementalXNISource.parse(false);
+ if (!gotMore)
+ {
+ // EOF reached without satisfying the request
+ clearCoRoutine(); // Drop connection, stop trying
+ // %TBD% deregister as its listener?
+ }
+ return gotMore;
+ }
+ catch(RuntimeException e)
+ {
+ throw e;
+ }
+ catch(Exception e)
+ {
+ throw new WrappedRuntimeException(e);
+ }
+
+ // %REVIEW% dead code
+ //clearCoRoutine();
+ //return false;
+ }
+
+ /** %REVIEW% XNI should let us support this better...
+ *
+ * Return the public identifier of the external subset,
+ * normalized as described in 4.2.2 External Entities [XML]. If there is
+ * no external subset or if it has no public identifier, this property
+ * has no value.
+ *
+ * @param the document type declaration handle
+ *
+ * @return the public identifier String object, or null if there is none.
+ */
+ public String getDocumentTypeDeclarationPublicIdentifier()
+ {
+ return super.getDocumentTypeDeclarationPublicIdentifier();
+ }
+
+
+
+ ////////////////////////////////////////////////////////////////////
+ // Implementation of XNI XMLDocumentHandler interface.
+ //
+ // %REVIEW% Hand off the SAX2DTM SAX event code, or copy/adapt method
+ // bodies? Performance may favor latter approach, but former is no worse
+ // than what's been happening on the parser's side of the fence and
+ // simplifies maintainance.
+ ////////////////////////////////////////////////////////////////////
+
+ /**
+ * Receive notification of a notation declaration.
+ *
+ * <p>By default, do nothing. Application writers may override this
+ * method in a subclass if they wish to keep track of the notations
+ * declared in a document.</p>
+ *
+ * @param name The notation name.
+ * @param publicId The notation public identifier, or null if not
+ * available.
+ * @param systemId The notation system identifier.
+ * @throws XNIException Any XNI exception, possibly
+ * wrapping another exception.
+ * @see org.xml.sax.DTDHandler#notationDecl
+ *
+ * @throws XNIException
+ */
+ public void notationDecl(String name, String publicId, String systemId)
+ throws XNIException
+ {
+ // no op
+ }
+
+ /**
+ * Receive notification of an unparsed entity declaration.
+ *
+ * <p>By default, do nothing. Application writers may override this
+ * method in a subclass to keep track of the unparsed entities
+ * declared in a document.</p>
+ *
+ * @param name The entity name.
+ * @param publicId The entity public identifier, or null if not
+ * available.
+ * @param systemId The entity system identifier.
+ * @param notationName The name of the associated notation.
+ * @throws XNIException Any XNI exception, possibly
+ * wrapping another exception.
+ * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+ *
+ * @throws XNIException
+ */
+ public void unparsedEntityDecl(
+ String name, String publicId, String systemId, String notationName)
+ throws XNIException
+ {
+ try
+ {
+ super.unparsedEntityDecl(name,publicId,systemId,notationName);
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+ /**
+ * Receive a Locator object for document events.
+ *
+ * <p>By default, do nothing. Application writers may override this
+ * method in a subclass if they wish to store the locator for use
+ * with other document events.</p>
+ *
+ * @param locator A locator for all XNI document events.
+ * @see org.xml.sax.ContentHandler#setDocumentLocator
+ * @see org.xml.sax.Locator
+ */
+ public void setDocumentLocator(XMLLocator locator)
+ {
+ m_locator_wrapper.setLocator(locator);
+ super.setDocumentLocator(m_locator_wrapper);
+ }
+
+ /**
+ * Receive notification of the beginning of the document.
+ *
+ * @throws XNIException Any XNI exception, possibly
+ * wrapping another exception.
+ * @see org.xml.sax.ContentHandler#startDocument
+ */
+ public void startDocument(XMLLocator locator,String encoding,Augmentations augs)
+ throws XNIException
+ {
+ if (DEBUG)
+ System.out.println("startDocument");
+
+ try
+ {
+ super.startDocument();
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+ /**
+ * Receive notification of the end of the document.
+ *
+ * @throws XNIException Any XNI exception, possibly
+ * wrapping another exception.
+ * @see org.xml.sax.ContentHandler#endDocument
+ */
+ public void endDocument(Augmentations augs) throws XNIException
+ {
+ if (DEBUG)
+ System.out.println("endDocument");
+
+ try
+ {
+ super.endDocument();
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+ /**
+ * Receive notification of the start of a Namespace mapping.
+ *
+ * <p>By default, do nothing. Application writers may override this
+ * method in a subclass to take specific actions at the start of
+ * each Namespace prefix scope (such as storing the prefix mapping).</p>
+ *
+ * @param prefix The Namespace prefix being declared.
+ * @param uri The Namespace URI mapped to the prefix.
+ * @throws XNIException Any XNI exception, possibly
+ * wrapping another exception.
+ * @see org.xml.sax.ContentHandler#startPrefixMapping
+ */
+ public void startPrefixMapping(String prefix,String uri,Augmentations augs)
+ throws XNIException
+ {
+ if (DEBUG)
+ System.out.println("startPrefixMapping: prefix: " + prefix + ", uri: "
+ + uri);
+ try
+ {
+ if(augs!=null &&
+ null!=augs.getItem(DTM2XNI.DTM2XNI_ADDED_STRUCTURE))
+ {
+ if (DEBUG)
+ System.out.println("\t***** Added by DTM2XNI; ignored here");
+
+ return; // Ignore it!
+ }
+
+
+ super.startPrefixMapping(prefix,uri);
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+ /**
+ * Receive notification of the end of a Namespace mapping.
+ *
+ * <p>By default, do nothing. Application writers may override this
+ * method in a subclass to take specific actions at the end of
+ * each prefix mapping.</p>
+ *
+ * @param prefix The Namespace prefix being declared.
+ * @throws XNIException Any XNI exception, possibly
+ * wrapping another exception.
+ * @see org.xml.sax.ContentHandler#endPrefixMapping
+ */
+ public void endPrefixMapping(String prefix, Augmentations augs)
+ throws XNIException
+ {
+ if (DEBUG)
+ System.out.println("endPrefixMapping: prefix: " + prefix);
+
+ try
+ {
+ if(augs!=null &&
+ null!=augs.getItem(DTM2XNI.DTM2XNI_ADDED_STRUCTURE))
+ {
+ if (DEBUG)
+ System.out.println("\t***** Added by DTM2XNI; ignored here");
+
+ return; // Ignore it!
+ }
+
+ super.endPrefixMapping(prefix);
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+ /**
+ * Receive notification of the start of an element.
+ *
+ * <p>By default, do nothing. Application writers may override this
+ * method in a subclass to take specific actions at the start of
+ * each element (such as allocating a new tree node or writing
+ * output to a file).</p>
+ *
+ * @param name The element type name.
+ *
+ * @param uri The Namespace URI, or the empty string if the
+ * element has no Namespace URI or if Namespace
+ * processing is not being performed.
+ * @param localName The local name (without prefix), or the
+ * empty string if Namespace processing is not being
+ * performed.
+ * @param qName The qualified name (with prefix), or the
+ * empty string if qualified names are not available.
+ * @param attributes The specified or defaulted attributes.
+ * @throws XNIException Any XNI exception, possibly
+ * wrapping another exception.
+ * @see org.xml.sax.ContentHandler#startElement
+ */
+ public void startElement(QName element, XMLAttributes attributes,
+ Augmentations augs)
+ //String uri, String localName, String qName, Attributes attributes)
+ throws XNIException
+ {
+ // %REVIEW% I've copied this verbatim and altered it for XNI.
+ // Is that overkill? Can we hand any of it back to the SAX layer?
+ // (I suspect not, darn it....)
+
+ if (DEBUG)
+ {
+ System.out.println("startElement: uri: " + element.uri +
+ ", localname: " + element.localpart +
+ ", qname: "+element.rawname+", atts: " + attributes);
+ }
+
+ boolean syntheticElement=false;
+
+ // Augs might be null if schema support not turned on in parser.
+ // Shouldn't arise in final operation (?); may arise during debugging
+ ElementPSVImpl elemPSVI=null;
+ XSTypeDefinition actualType =null;
+ XPath2Type xp2type=null;
+ if(augs!=null)
+ {
+ // Node added by DTM2XNI?
+ syntheticElement = null!=augs.getItem(DTM2XNI.DTM2XNI_ADDED_STRUCTURE);
+
+ // Extract Experimental Xerces PSVI data
+ elemPSVI=(ElementPSVImpl)augs.getItem(org.apache.xerces.impl.Constants.ELEMENT_PSVI);
+ xp2type=new XPath2Type(elemPSVI,false);
+ actualType =
+ (elemPSVI==null) ? null : elemPSVI.getTypeDefinition();
+ if (DEBUG)
+ {
+ String actualExpandedQName=xp2type.getTargetNamespace()+":"+xp2type.getTypeName();
+
+ System.out.println("\ttypeDefinition (actual): "+ actualType +
+ "\n\t\ttype expanded-qname: " + actualExpandedQName +
+// "\n\tDerived from builtin string: " + actualType.derivedFrom(SCHEMANS,"string") +
+ "\n\tSynthesized by DTM2XNI: "+syntheticElement
+ );
+ } //DEBUG
+ }// augs
+
+ if(DEBUG && attributes!=null)
+ {
+ int n = attributes.getLength();
+ if(n==0)
+ System.out.println("\tempty attribute list");
+ else for (int i = 0; i < n; i++)
+ {
+ System.out.println("\t attr: uri: " + attributes.getURI(i) +
+ ", localname: " + attributes.getLocalName(i) +
+ ", qname: " + attributes.getQName(i) +
+ ", type: " + attributes.getType(i) +
+ ", value: " + attributes.getValue(i)
+ );
+ // Experimental Xerces PSVI data
+ Augmentations attrAugs=attributes.getAugmentations(i);
+ AttributePSVImpl attrPSVI=(AttributePSVImpl)attrAugs.getItem(org.apache.xerces.impl.Constants.ATTRIBUTE_PSVI);
+ XPath2Type xp2attrtype=new XPath2Type(attrPSVI,true);
+ XSTypeDefinition actualAttrType=(attrPSVI==null) ? null : attrPSVI.getTypeDefinition();
+ String actualExpandedQName=(actualAttrType==null) ? null : actualAttrType.getNamespace()+":"+actualAttrType.getName();
+ // Node added by DTM2XNI?
+ boolean syntheticAttribute = null!=attrAugs.getItem(DTM2XNI.DTM2XNI_ADDED_STRUCTURE);
+
+ actualExpandedQName=xp2attrtype.getTargetNamespace()+
+ ":"+ xp2attrtype.getTypeName();
+
+ System.out.println("\t\ttypeDefinition (actual): "+ actualAttrType +
+ "\n\t\t\ttype expanded-qname: " + actualExpandedQName
+ );
+ if(actualAttrType!=null)
+ System.out.println(
+ "\n\t\tSynthesized by DTM2XNI: "+syntheticAttribute
+ );
+ } // dump all attrs
+ } // DEBUG
+
+
+ if(syntheticElement)
+ {
+ if (DEBUG)
+ System.out.println("\t***** Added by DTM2XNI; ignored here");
+
+ return; // Ignore it!
+ }
+
+ charactersFlush();
+
+
+ int exName = m_expandedNameTable.getExpandedTypeID(element.uri, element.localpart, DTM.ELEMENT_NODE);
+ String prefix = getPrefix(element.rawname, element.uri);
+ int prefixIndex = (null != element.prefix)
+ ? m_valuesOrPrefixes.stringToIndex(element.rawname) : 0;
+ int elemNode = addNode(DTM.ELEMENT_NODE, exName,
+ m_parents.peek(), m_previous, prefixIndex, true,
+ xp2type);
+
+ if(m_indexing)
+ indexNode(exName, elemNode);
+
+ m_parents.push(elemNode);
+
+ int startDecls = m_contextIndexes.peek();
+ int nDecls = m_prefixMappings.size();
+ int prev = DTM.NULL;
+
+ if(!m_pastFirstElement)
+ {
+ // SPECIAL CASE: Implied declaration at root element
+ prefix="xml";
+ String declURL = "http://www.w3.org/XML/1998/namespace";
+ exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
+ int val = m_valuesOrPrefixes.stringToIndex(declURL);
+ // %REVIEW% I don't _think_ we need datatype on namespaces...?
+ prev = addNode(DTM.NAMESPACE_NODE, exName, elemNode,
+ prev, val, false);
+ m_pastFirstElement=true;
+ }
+
+ for (int i = startDecls; i < nDecls; i += 2)
+ {
+ prefix = (String) m_prefixMappings.elementAt(i);
+
+ if (prefix == null)
+ continue;
+
+ String declURL = (String) m_prefixMappings.elementAt(i + 1);
+
+ exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
+
+ int val = m_valuesOrPrefixes.stringToIndex(declURL);
+
+ // %REVIEW% I don't _think_ we need datatype on namespaces...?
+ prev = addNode(DTM.NAMESPACE_NODE, exName, elemNode,
+ prev, val, false);
+ }
+
+ int n = attributes.getLength();
+
+ for (int i = 0; i < n; i++)
+ {
+ String attrUri = attributes.getURI(i);
+
+
+
+ String attrQName = attributes.getQName(i);
+ String valString = attributes.getValue(i);
+
+ prefix = getPrefix(attrQName, attrUri);
+
+ int nodeType;
+
+ if ((null != attrQName)
+ && (attrQName.equals("xmlns")
+ || attrQName.startsWith("xmlns:")))
+ {
+ if (declAlreadyDeclared(prefix))
+ continue; // go to the next attribute.
+
+ nodeType = DTM.NAMESPACE_NODE;
+ } // NS special-handling
+ else
+ {
+ nodeType = DTM.ATTRIBUTE_NODE;
+
+ if (attributes.getType(i).equalsIgnoreCase("ID"))
+ setIDAttribute(valString, elemNode);
+ } // Attr/ID special handling
+
+
+ // Bit of a hack... if somehow valString is null, stringToIndex will
+ // return -1, which will make things very unhappy.
+ if(null == valString)
+ valString = "";
+
+ int val = m_valuesOrPrefixes.stringToIndex(valString);
+ String attrLocalName = attributes.getLocalName(i);
+
+ if (null != prefix)
+ {
+
+ prefixIndex = m_valuesOrPrefixes.stringToIndex(attrQName);
+
+ int dataIndex = m_data.size();
+
+ m_data.addElement(prefixIndex);
+ m_data.addElement(val);
+
+ val = -dataIndex;
+ } // Prefix handling
+
+ exName = m_expandedNameTable.getExpandedTypeID(attrUri, attrLocalName, nodeType);
+
+ // Experimental Xerces PSVI data
+ Augmentations attrAugs=attributes.getAugmentations(i);
+ boolean syntheticAttribute= null != attrAugs.getItem(DTM2XNI.DTM2XNI_ADDED_STRUCTURE);
+ if(syntheticAttribute)
+ {
+ if (DEBUG)
+ System.out.println("\t***** Attr {"+attrUri+"}"+attrLocalName+" added by DTM2XNI; ignored here");
+ return; // Ignore it!
+ } // Synthetic suppression
+
+ AttributePSVImpl attrPSVI=(AttributePSVImpl)attrAugs.getItem(org.apache.xerces.impl.Constants.ATTRIBUTE_PSVI);
+ XPath2Type xp2attrtype=new XPath2Type(attrPSVI,true);
+
+ prev = addNode(nodeType, exName, elemNode, prev, val,
+ false, xp2attrtype);
+ } // Attribute list loop
+
+
+ if(DTM2XNI.SUPPRESS_XSI_ATTRIBUTES)
+ {
+ // Were any XNI attributes passed _around_ the validator,
+ // using element augmentations? If so, magic them back
+ // into being attributes.
+ //
+ // See comments in DTM2XNI. Is this trip REALLY necessary?)
+ java.util.Vector v=(java.util.Vector)augs.getItem(DTM2XNI.SUPPRESSED_XSI);
+ if(v!=null)
+ {
+ for(int i=v.size()-1;i>=0;--i)
+ {
+ Object[] ary=(Object[])v.elementAt(i); // {QName,"CDATA",value}
+ QName aqq=(QName) ary[0];
+ String valString=(String) ary[2];
+ if(null == valString)
+ valString = "";
+ int val = m_valuesOrPrefixes.stringToIndex(valString);
+ exName = m_expandedNameTable.getExpandedTypeID(
+ aqq.uri,aqq.localpart, DTM.ATTRIBUTE_NODE);
+
+ prev=addNode(DTM.ATTRIBUTE_NODE,exName,elemNode,prev,val,
+ false,null);
+ }
+ }
+
+ }
+
+ if (DTM.NULL != prev)
+ m_nextsib.setElementAt(DTM.NULL,prev);
+
+ if (null != m_wsfilter)
+ {
+ short wsv = m_wsfilter.getShouldStripSpace(makeNodeHandle(elemNode), this);
+ boolean shouldStrip = (DTMWSFilter.INHERIT == wsv)
+ ? getShouldStripWhitespace()
+ : (DTMWSFilter.STRIP == wsv);
+
+ pushShouldStripWhitespace(shouldStrip);
+ }
+
+ m_previous = DTM.NULL;
+
+ m_contextIndexes.push(m_prefixMappings.size()); // for the children.
+ }
+
+ /**
+ * Receive notification of the end of an element.
+ *
+ * @param name The element type name.
+ * @param attributes The specified or defaulted attributes.
+ *
+ * @param uri The Namespace URI, or the empty string if the
+ * element has no Namespace URI or if Namespace
+ * processing is not being performed.
+ * @param localName The local name (without prefix), or the
+ * empty string if Namespace processing is not being
+ * performed.
+ * @param qName The qualified XML 1.0 name (with prefix), or the
+ * empty string if qualified names are not available.
+ * @throws XNIException Any XNI exception, possibly
+ * wrapping another exception.
+ * @see org.xml.sax.ContentHandler#endElement
+ */
+ public void endElement(QName element,Augmentations augs) throws XNIException
+ {
+ if (DEBUG)
+ System.out.println("endElement: uri: " + element.uri +
+ ", localname: " + element.localpart + ", qname: "+element.rawname);
+
+ if(null!=augs && null!=augs.getItem(DTM2XNI.DTM2XNI_ADDED_STRUCTURE))
+ {
+ if (DEBUG)
+ System.out.println("\t***** Added by DTM2XNI; ignored here");
+
+ return; // Ignore it!
+ }
+
+ try
+ {
+ super.endElement(element.uri,element.localpart,element.rawname);
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+
+ // Complication: Type information is obtained at startElement.
+ // VALIDITY isn't known 'till the endElement. XPath2 type is actually
+ // a combination of information from both. NOTE that this largely defeats
+ // attempts to implement XNI2DTM as a standard demand-mode DTM; we don't
+ // know the node type until we _exit_ the node; the nextNode() logic
+ // would have to be rewritten to deal with that, and very little streaming
+ // would actually result.
+
+ {
+ // After super.endElement, m_previous is the element we're ending.
+ // Try to record as default for this nodetype,
+ // using our type wrapper which records XPath2 resolved NS/localname
+
+ ItemPSVI elemPSVI=null;
+ XPath2Type actualType =null;
+ if(augs!=null)
+ {
+ elemPSVI=(ItemPSVI) augs.getItem(org.apache.xerces.impl.Constants.ELEMENT_PSVI);
+
+ /** %BUG% Work around Xerces' bad habit of not telling us what the type was
+ * at the time endElement() is called, and (obviously) not telling us
+ * validity at the time startElement() is called. I hope to convince them
+ * to change the former.
+ * */
+ XSSimpleTypeDefinition member=elemPSVI.getMemberTypeDefinition();
+ XSTypeDefinition type=elemPSVI.getTypeDefinition();
+
+ actualType =new XPath2Type(elemPSVI,member,type,false);
+ }
+
+ if(!m_expandedNameTable.setSchemaType(m_exptype.elementAt(m_previous),
+ actualType)
+ )
+ {
+ m_schemaTypeOverride.setElementAt(actualType,m_previous);
+ }
+ }
+
+ }
+
+ /** 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
+ {
+ // %OPT% We could skip the pushes and pops and save some cycles...
+ startElement(element,attributes,augs);
+ endElement(element,augs);
+ }
+
+ /**
+ * Receive notification of character data inside an element.
+ *
+ * <p>By default, do nothing. Application writers may override this
+ * method to take specific actions for each chunk of character data
+ * (such as adding the data to a node or buffer, or printing it to
+ * a file).</p>
+ *
+ * @param ch The characters.
+ * @param start The start position in the character array.
+ * @param length The number of characters to use from the
+ * character array.
+ * @throws XNIException Any XNI exception, possibly
+ * wrapping another exception.
+ * @see org.xml.sax.ContentHandler#characters
+ */
+ public void characters(org.apache.xerces.xni.XMLString text,Augmentations augs) throws XNIException
+ {
+ try
+ {
+ super.characters(text.ch, text.offset, text.length);
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+ /**
+ * Receive notification of ignorable whitespace in element content.
+ *
+ * <p>By default, do nothing. Application writers may override this
+ * method to take specific actions for each chunk of ignorable
+ * whitespace (such as adding data to a node or buffer, or printing
+ * it to a file).</p>
+ *
+ * @param ch The whitespace characters.
+ * @param start The start position in the character array.
+ * @param length The number of characters to use from the
+ * character array.
+ * @throws XNIException Any XNI exception, possibly
+ * wrapping another exception.
+ * @see org.xml.sax.ContentHandler#ignorableWhitespace
+ */
+ public void ignorableWhitespace(org.apache.xerces.xni.XMLString text, Augmentations augs)
+ throws XNIException
+ {
+ // %OPT% We can probably take advantage of the fact that we know this
+ // is whitespace... or has that been dealt with at the source?
+ try
+ {
+ super.characters(text.ch, text.offset, text.length);
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+ /**
+ * Receive notification of a processing instruction.
+ *
+ * <p>By default, do nothing. Application writers may override this
+ * method in a subclass to take specific actions for each
+ * processing instruction, such as setting status variables or
+ * invoking other methods.</p>
+ *
+ * @param target The processing instruction target.
+ * @param data The processing instruction data, or null if
+ * none is supplied.
+ * @throws XNIException Any XNI exception, possibly
+ * wrapping another exception.
+ * @see org.xml.sax.ContentHandler#processingInstruction
+ */
+ public void processingInstruction(String target,org.apache.xerces.xni.XMLString data,Augmentations augs)
+ throws XNIException
+ {
+ if (DEBUG)
+ System.out.println("processingInstruction: target: " + target +", data: "+data);
+
+ try
+ {
+ // %REVIEW% Can we avoid toString? I don't think so, given our
+ // current data structures, but that bears reconsideration
+ super.processingInstruction(target,data.toString());
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+ /**
+ * Report the beginning of an entity in content.
+ *
+ * <p><strong>NOTE:</entity> entity references in attribute
+ * values -- and the start and end of the document entity --
+ * are never reported.</p>
+ *
+ * <p>The start and end of the external DTD subset are reported
+ * using the pseudo-name "[dtd]". All other events must be
+ * properly nested within start/end entity events.</p>
+ *
+ * <p>Note that skipped entities will be reported through the
+ * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity}
+ * event, which is part of the ContentHandler interface.</p>
+ *
+ * @param name The name of the entity. If it is a parameter
+ * entity, the name will begin with '%'.
+ * @throws SAXException The application may raise an exception.
+ * @see #endEntity
+ * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
+ * @see org.xml.sax.ext.DeclHandler#externalEntityDecl
+ */
+ public void startGeneralEntity(String name,XMLResourceIdentifier identifier,
+ String encoding,Augmentations augs)
+ throws XNIException
+ {
+
+ // no op
+ }
+
+ /**
+ * Report the end of an entity.
+ *
+ * @param name The name of the entity that is ending.
+ * @throws SAXException The application may raise an exception.
+ * @see #startEntity
+ */
+ public void endGeneralEntity(String name,Augmentations augs) throws XNIException
+ {
+
+ // no op
+ }
+
+ /** 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
+ {
+
+ // no op
+ }
+
+
+ /** 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
+ {
+
+ // no op
+ }
+
+
+ /**
+ * Report the start of a CDATA section.
+ *
+ * <p>The contents of the CDATA section will be reported through
+ * the regular {@link org.xml.sax.ContentHandler#characters
+ * characters} event.</p>
+ *
+ * @throws SAXException The application may raise an exception.
+ * @see #endCDATA
+ */
+ public void startCDATA(Augmentations augs) throws XNIException
+ {
+ try
+ {
+ super.startCDATA();
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+
+ }
+
+ /**
+ * Report the end of a CDATA section.
+ *
+ * @throws SAXException The application may raise an exception.
+ * @see #startCDATA
+ */
+ public void endCDATA(Augmentations augs) throws XNIException
+ {
+ try
+ {
+ super.endCDATA();
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+ /**
+ * Report an XML comment anywhere in the document.
+ *
+ * <p>This callback will be used for comments inside or outside the
+ * document element, including comments in the external DTD
+ * subset (if read).</p>
+ *
+ * @param ch An array holding the characters in the comment.
+ * @param start The starting position in the array.
+ * @param length The number of characters to use from the array.
+ * @throws SAXException The application may raise an exception.
+ */
+ public void comment(org.apache.xerces.xni.XMLString text,Augmentations augs) throws XNIException
+ {
+ try
+ {
+ super.comment(text.ch,text.offset,text.length);
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+
+ /** Helper class: Present XNI Locator info as SAX Locator
+ * */
+ private class LocatorWrapper
+ implements org.xml.sax.Locator
+ {
+ XMLLocator locator;
+ String publicId=null;
+ String systemId=null;
+
+ public void setLocator(XMLLocator locator)
+ { this.locator=locator; }
+
+ public void setPublicId(String publicId)
+ { this.publicId=publicId; }
+
+ public void setSystemId(String systemId)
+ { this.systemId=systemId; }
+
+ public int getColumnNumber()
+ {
+ return locator.getColumnNumber();
+ }
+ public int getLineNumber()
+ {
+ return locator.getLineNumber();
+ }
+ public String getPublicId()
+ {
+ return publicId;
+ }
+ public String getSystemId()
+ {
+ return systemId;
+ }
+ }
+
+ /** 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
+ {
+ // no op
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ // XNI error handler
+
+ public void warning(java.lang.String domain,
+ java.lang.String key,
+ XMLParseException exception)
+ throws XNIException
+ {
+ // %REVIEW% Should be routed to the JAXP error listener, presumably.
+ // What's the easiest way to get that from here?
+ // It's available from the xctxt, but I'm not sure how to get that
+ // from the DTM structures; the connections mostly go the other way.
+ System.err.println(exception);
+ }
+ public void error(java.lang.String domain,
+ java.lang.String key,
+ XMLParseException exception)
+ throws XNIException
+ {
+ // %REVIEW% Should be routed to the JAXP error listener, presumably.
+ // see warning()
+ System.err.println(exception);
+ }
+ public void fatalError(java.lang.String domain,
+ java.lang.String key,
+ XMLParseException exception)
+ throws XNIException
+ {
+ // %REVIEW% Should be routed to the JAXP error listener, presumably.
+ // see warning()
+ throw exception;
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ // XNI DTD handler. Needed for unparsed entities, but to get that
+ // have to accept the other calls... which means we need to know the start
+ // and end of the DTD to prevent DTD comments from being taken as
+ // part of the main document.
+
+ public void startDTD(XMLLocator locator,
+ Augmentations augmentations)
+ throws XNIException
+ {
+ try
+ {
+ super.startDTD("unknownDocumentTypeName",locator.getPublicId(),locator.getLiteralSystemId());
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+ public void startParameterEntity(java.lang.String name,
+ XMLResourceIdentifier identifier,
+ java.lang.String encoding,
+ Augmentations augmentations)
+ throws XNIException
+ {
+ // no op
+ }
+
+ // textDecl already handled
+
+ public void endParameterEntity(java.lang.String name,
+ Augmentations augmentations)
+ throws XNIException
+ {
+ // no op
+ }
+ public void startExternalSubset(XMLResourceIdentifier resource,Augmentations augmentations)
+ throws XNIException
+ {
+ // no op
+ }
+ public void endExternalSubset(Augmentations augmentations)
+ throws XNIException
+ {
+ // no op
+ }
+
+ // comment already handled, including suppression during the DTD
+ // processing instruction already handled. NOT currently suppressed during DTD?
+
+ public void elementDecl(java.lang.String name,
+ java.lang.String contentModel,
+ Augmentations augmentations)
+ throws XNIException
+ {
+ //no op
+ }
+ public void startAttlist(java.lang.String elementName,
+ Augmentations augmentations)
+ throws XNIException
+ {
+ //no op
+ }
+
+ public void attributeDecl(String elementName,String attributeName,
+ java.lang.String type, java.lang.String[] enumeration,
+ String defaultType, XMLString defaultValue,
+ XMLString nonNormalizedDefaultValue, Augmentations augmentations)
+ throws XNIException
+ {
+ // no op
+ }
+
+ public void endAttlist(Augmentations augmentations)
+ throws XNIException
+ {
+ //no op
+ }
+ public void internalEntityDecl(String name, XMLString text,
+ XMLString nonNormalizedText,
+ Augmentations augmentations)
+ throws XNIException
+ {
+ //no op
+ }
+ public void externalEntityDecl(java.lang.String name,
+ XMLResourceIdentifier identifier,
+ Augmentations augmentations)
+ throws XNIException
+ {
+ //no op
+ }
+
+ public void unparsedEntityDecl(java.lang.String name,
+ XMLResourceIdentifier identifier,
+ java.lang.String notation,
+ Augmentations augmentations)
+ throws XNIException
+ {
+ // This one's the wnole point of the exercise...
+ try
+ {
+ super.unparsedEntityDecl(name,identifier.getPublicId(),identifier.getLiteralSystemId(),notation);
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+ public void notationDecl(java.lang.String name,
+ XMLResourceIdentifier identifier,
+ Augmentations augmentations)
+ throws XNIException
+ {
+ // no op
+ }
+ public void startConditional(short type,
+ Augmentations augmentations)
+ throws XNIException
+ {
+ // no op
+ }
+
+ public void ignoredCharacters(XMLString text, Augmentations augmentations)
+ throws XNIException
+ {
+ // no op
+ }
+ public void endConditional(Augmentations augmentations)
+ throws XNIException
+ {
+ // no op
+ }
+
+ public void endDTD(Augmentations augmentations)
+ throws XNIException
+ {
+ try
+ {
+ super.endDTD();
+ }
+ catch(SAXException e)
+ {
+ throw new XNIException(e);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
+ // %REVIEW% SAX APIs are currently _blocked_ for debugging purposes. We can
+ // re-enable them if/when we fold the XNI support back into the main SAX2DTM
+ ////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////
+
+
+ // Implementation of DTDHandler interface.
+
+ // SAME AS XNI? OR DID WE RETAIN THEM ABOVE FOR OTHER REASONS?
+ //public void notationDecl(String name, String publicId, String systemId)
+ // throws SAXException
+ // public void unparsedEntityDecl(
+ // String name, String publicId, String systemId, String notationName)
+ // throws SAXException
+
+ // Implementation of ContentHandler interface.
+
+ public void setDocumentLocator(org.xml.sax.Locator locator)
+ {
+ throw new RuntimeException(UNEXPECTED+"setDocumentLocator");
+ }
+ public void startDocument() throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"startDocument");
+ }
+ public void endDocument() throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"endDocument");
+ }
+ public void startPrefixMapping(String prefix, String uri)
+ throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"startPrefixMapping");
+ }
+ public void endPrefixMapping(String prefix) throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"endPrefixMapping");
+ }
+ public void startElement(
+ String uri, String localName, String qName, org.xml.sax.Attributes attributes)
+ throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"startElement");
+ }
+ public void endElement(String uri, String localName, String qName)
+ throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"endElement");
+ }
+ public void characters(char ch[], int start, int length) throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"characters");
+ }
+ public void ignorableWhitespace(char ch[], int start, int length)
+ throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"ignorableWhitespace");
+ }
+ public void processingInstruction(String target, String data)
+ throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"processingInstruction");
+ }
+ public void skippedEntity(String name) throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"skippedEntity");
+ }
+
+ // Implementation of SAX error handler
+
+ public void warning(SAXParseException e) throws SAXException
+ {
+ // %REVIEW% Is there anyway to get the JAXP error listener here?
+ throw new SAXException(UNEXPECTED+"Warning: "+e.getMessage());
+ }
+ public void error(SAXParseException e) throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"Error: "+e.getMessage());
+ }
+ public void fatalError(SAXParseException e) throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"Fatal Error: "+e.getMessage());
+ }
+
+ // Implementation of SAX DeclHandler interface.
+
+ public void elementDecl(String name, String model) throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"elementDecl "+name);
+ }
+ public void attributeDecl(
+ String eName, String aName, String type, String valueDefault, String value)
+ throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"attributeDecl "+aName);
+ }
+ public void internalEntityDecl(String name, String value)
+ throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"internalEntityDecl "+name);
+ }
+ public void externalEntityDecl(
+ String name, String publicId, String systemId) throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"externalEntityDecl "+name);
+ }
+
+ // Implementation of the LexicalHandler interface.
+ public void startDTD(String name, String publicId, String systemId)
+ throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"startDTD");
+ }
+ public void endDTD() throws SAXException
+ {
+ throw new SAXException(UNEXPECTED+"endDTD");
+ }
+
+} // XNI2DTM
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/XNISource.java b/src/org/apache/xml/dtm/ref/xni2dtm/XNISource.java
new file mode 100644
index 0000000..e630de6
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/XNISource.java
@@ -0,0 +1,326 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The name "Apache Software Foundation" must not be used to endorse or
+ * promote products derived from this software without prior written
+ * permission. For written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.transform.sax.SAXSource;
+
+import java.lang.String;
+
+import java.io.OutputStream;
+import java.io.Writer;
+
+import org.apache.xerces.xni.parser.XMLDocumentScanner;
+import org.apache.xerces.xni.parser.XMLDocumentSource;
+import org.apache.xerces.xni.parser.XMLInputSource;
+import org.apache.xerces.xni.XMLDocumentHandler;
+import org.apache.xerces.xni.parser.XMLErrorHandler;
+import org.apache.xerces.xni.parser.XMLParserConfiguration;
+
+/**
+ * Acts as an holder for XNI-style Source.
+ * Should be made more compatable with JAXP Source
+ * (eg, accept JAXP InputSource and convert to XNI?)
+ * Should this be moved to javax.xml.transform?
+ */
+public class XNISource implements Source {
+ XMLDocumentScanner docScanner;
+ XMLDocumentSource eventSource;
+ XMLInputSource xniInputSource;
+
+ // This should be
+ // XMLParserConfiguration parserConfiguration;
+ // but the reset() operation is unfortunately _NOT_ part of the
+ // architecture of the Configuration!
+ DOMValidationConfigurationSwipedFromXerces parserConfiguration;
+
+ /**
+ * If {@link javax.xml.transform.TransformerFactory#getFeature}
+ * returns true when passed this value as an argument,
+ * the Transformer supports Source input of this type.
+ */
+ public static final String FEATURE =
+ "http://org.apache.xml.dtm.ref.xni2dtm.XNISource/feature";
+
+ /**
+ * Zero-argument default constructor. If this constructor
+ * is used, and no other method is called, the
+ * {@link javax.xml.transform.Transformer}
+ * assumes an empty input tree, with a default root node.
+ */
+ public XNISource() {}
+
+ /**
+ * Create a <code>XNISource</code>, using an {@link org.xml.XNI.XMLReader}
+ * and a XNI InputSource. The {@link javax.xml.transform.Transformer}
+ * or {@link javax.xml.transform.XNI.XNITransformerFactory} will set itself
+ * to be the reader's {@link org.xml.XNI.ContentHandler}, and then will call
+ * reader.parse(inputSource).
+ *
+ * @param reader An XMLReader to be used for the parse. Must also implement
+ * XMLParserConfiguration. (That may make this a non-useful method
+ * as it stands. %REVIEW%.)
+ * @param inputSource A XNI input source reference that must be non-null
+ * and that will be passed to the reader parse method.
+ */
+ public XNISource(XMLDocumentScanner reader, XMLInputSource inputSource)
+ {
+ this(reader,(XMLParserConfiguration)reader,reader,inputSource);
+ }
+
+ /**
+ * Create a <code>XNISource</code>, using an {@link org.xml.xni.XMLDocumentScanner}
+ * (which we will send the parse request to), an {@link org.xml.xni.XMLDocumentSource}
+ * (which we will expect the events from) and a XNI InputSource. The first two
+ * are separated because there might be a filtering pipeline between the
+ * scanner and our own immediate source.
+ *
+ * The {@link javax.xml.transform.Transformer}
+ * or {@link javax.xml.transform.XNI.XNITransformerFactory} will set itself
+ * to be the reader's {@link org.xml.XNI.ContentHandler}, and then will call
+ * reader.parse(inputSource).
+ *
+ * @param reader An XMLReader to be used for the parse.
+ * @param inputSource A XNI input source reference that must be non-null
+ * and that will be passed to the reader parse method.
+ */
+ public XNISource(XMLDocumentScanner reader,
+ XMLParserConfiguration parserConfiguration,
+ XMLDocumentSource eventSource,
+ XMLInputSource inputSource)
+ {
+ this.docScanner = reader;
+ this.eventSource = eventSource;
+ this.xniInputSource = inputSource;
+ // Sloppy, but XMLParserConfiguration has no reset() operation
+ // and reset _must_ be performed late (eg after setting the
+ // error handler).
+ this.parserConfiguration = (DOMValidationConfigurationSwipedFromXerces)parserConfiguration;
+ }
+
+
+
+ /**
+ * Create a <code>XNISource</code>, using a XNI <code>InputSource</code>.
+ * The {@link javax.xml.transform.Transformer} or
+ * {@link javax.xml.transform.XNI.XNITransformerFactory} creates a
+ * reader via {@link org.xml.XNI.helpers.XMLReaderFactory}
+ * (if setXMLReader is not used), sets itself as
+ * the reader's {@link org.xml.XNI.ContentHandler}, and calls
+ * reader.parse(inputSource).
+ *
+ * @param inputSource An input source reference that must be non-null
+ * and that will be passed to the parse method of the reader.
+ */
+ public XNISource(XMLInputSource inputSource) {
+ this.xniInputSource = inputSource;
+ }
+
+ /**
+ * Convert SAX source to XNI source (by swiping its input)
+ *
+ * @param inputSource An input source reference that must be non-null
+ * and that will be passed to the parse method of the reader.
+ */
+ public XNISource(SAXSource saxSource) {
+ setInputSource(saxSource.getInputSource());
+ }
+
+ /**
+ * Read from SAX-style InputSource
+ *
+ * @param inputSource An input source reference that must be non-null
+ * and that will be passed to the parse method of the reader.
+ */
+ public void setInputSource(org.xml.sax.InputSource saxInputSource) {
+ if(saxInputSource.getCharacterStream()!=null)
+ this.xniInputSource=new XMLInputSource(
+ saxInputSource.getPublicId(),
+ saxInputSource.getSystemId(),
+ null,
+ saxInputSource.getCharacterStream(),
+ saxInputSource.getEncoding()
+ );
+ else if(saxInputSource.getByteStream()!=null)
+ this.xniInputSource=new XMLInputSource(
+ saxInputSource.getPublicId(),
+ saxInputSource.getSystemId(),
+ null,
+ saxInputSource.getByteStream(),
+ saxInputSource.getEncoding()
+ );
+ else
+ this.xniInputSource=new XMLInputSource(
+ saxInputSource.getPublicId(),
+ saxInputSource.getSystemId(),
+ null);
+ }
+
+ /**
+ * Set the XMLReader to be used for the Source.
+ * Be sure to set the document handler _after_ this.
+ * %REVIEW%: Should we save and reassert that value?
+ *
+ * @param reader A valid XMLReader or XMLFilter reference.
+ */
+ public void setXMLReader(org.apache.xerces.xni.parser.XMLDocumentScanner reader) {
+ this.docScanner = reader;
+ }
+
+ /**
+ * Set the XNI InputSource to be used for the Source.
+ *
+ * @param inputSource A valid InputSource reference.
+ */
+ public void setInputSource(XMLInputSource inputSource) {
+ this.xniInputSource = inputSource;
+ }
+
+ /**
+ * Get the XNI InputSource to be used for the Source.
+ *
+ * @return A valid InputSource reference, or null.
+ */
+ public XMLInputSource getInputSource() {
+ return xniInputSource;
+ }
+
+ /**
+ * Set the XNI DocumentHandler to receive our output. Note that
+ * this ties to the event source, which is not necessarily the
+ * scanner.
+ *
+ * @param inputSource A valid XMLDocumentHandler reference.
+ */
+ public void setDocumentHandler(XMLDocumentHandler target)
+ {
+ eventSource.setDocumentHandler(target);
+ }
+
+ /**
+ * Set the XNI ErrorHandler to receive our output. Note that
+ * this ties to the parser configuration.
+ *
+ * @param inputSource A valid XMLDocumentHandler reference.
+ */
+ public void setErrorHandler(XMLErrorHandler target)
+ {
+ parserConfiguration.setErrorHandler(target);
+ }
+
+ /**
+ * Start/resume parsing.
+ * Note that this gets passed to the scanner, which is not necessarily
+ * the immediate event source.
+ *
+ * @param toCompletion False for incremental parse, true to read the
+ * rest of the document.
+ */
+ public void reset() throws java.io.IOException
+ {
+ parserConfiguration.reset();
+ }
+
+ /**
+ * Start/resume parsing.
+ * Note that this gets passed to the scanner, which is not necessarily
+ * the immediate event source.
+ *
+ * @param toCompletion False for incremental parse, true to read the
+ * rest of the document.
+ */
+ public void scanDocument(boolean toCompletion) throws java.io.IOException
+ {
+ docScanner.scanDocument(toCompletion);
+ }
+
+
+ /**
+ * Set the system identifier for this Source. If an input source
+ * has already been set, it will set the system ID or that
+ * input source, otherwise it will create a new input source.
+ *
+ * <p>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 open a connection to the URI only if
+ * no byte stream or character stream is specified).</p>
+ *
+ * @param systemId The system identifier as a URI string.
+ */
+ public void setSystemId(String systemId) {
+
+ if (null == xniInputSource) {
+ xniInputSource = new XMLInputSource(null,systemId,null);
+ } else {
+ xniInputSource.setSystemId(systemId);
+ }
+ }
+
+ /**
+ * Get the base ID (URI or system ID) from where URIs
+ * will be resolved.
+ *
+ * @return Base URL for the Source, or null.
+ */
+ public String getSystemId() {
+
+ return (null != xniInputSource)
+ ? xniInputSource.getSystemId()
+ : null;
+ }
+}
+
diff --git a/src/org/apache/xml/dtm/ref/xni2dtm/XPath2Type.java b/src/org/apache/xml/dtm/ref/xni2dtm/XPath2Type.java
new file mode 100644
index 0000000..9f59f5f
--- /dev/null
+++ b/src/org/apache/xml/dtm/ref/xni2dtm/XPath2Type.java
@@ -0,0 +1,656 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.xml.dtm.ref.xni2dtm;
+
+import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
+import org.apache.xerces.impl.dv.ValidatedInfo;
+import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl;
+import org.apache.xerces.impl.validation.ValidationState;
+import org.apache.xerces.impl.xs.XSTypeDecl;
+import org.apache.xerces.impl.xs.psvi.XSSimpleTypeDefinition;
+import org.apache.xerces.impl.xs.psvi.XSTypeDefinition;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.psvi.ItemPSVI;
+import org.apache.xml.dtm.DTMSequence;
+
+ /** The full XNI ItemPSVI is far too heavy-weight for
+ * our needs. But their XSTypeDecl isn't quite heavy enough; it gives
+ * us the actual member type, but that may be anonymous... so to get
+ * what XPath2 considers the proper typename, we need to examine
+ * additional fields as well. This class is an attempt to compromise by
+ * resolving the typename and storing that alongside the member type.
+ *
+ * A more efficient solution undoubtedly exists. But since XNI's PSVI
+ * APIs are still in flux, and since I'm just trying to get an initial
+ * demo running, this will suffice for now.
+ * %REVIEW% periodically!
+ * */
+public class XPath2Type
+{
+ public XSTypeDefinition m_xniType;
+ public String m_namespace;
+ public String m_localName;
+
+ /** Constructor for our internal type representation
+ * We will extract the low-level XSTypeDecl for the Member Type,
+ * and determine the proper namespace and localname. Other data
+ * can (hopefully) be GC'd after we're done. This is still NOT
+ * a lightweight beast.
+ *
+ * @param psvi XNI Post-Schema-Validation Infoset annotation.
+ * @param isAttr True iff we're defining type for an attribute.
+ * */
+ public XPath2Type(ItemPSVI psvi, boolean isAttr)
+ {
+ // First get the member type.
+ m_xniType= (psvi==null) ? null : psvi.getTypeDefinition();
+
+ // Now resolve the typename.
+ // There are some quibbles about algorithm; see comments on
+ // the resolve methods.
+ heavyResolveTypeName(psvi,isAttr);
+ }
+
+ /** Constructor for Xerces workaround
+ * (Xerces isn't reminding us of type at the time it provides
+ * validity, so XNI2DTM is passing that data around via a stack.
+ * This is a kluge and I hope to convince Xerces to fix it.)
+ *
+ * @param psvi XNI Post-Schema-Validation Infoset annotation.
+ * @param isAttr True iff we're defining type for an attribute.
+ * */
+ public XPath2Type(ItemPSVI psvi, XSSimpleTypeDefinition member, XSTypeDefinition type, boolean isAttr)
+ {
+ // First get the member type.
+ m_xniType= (psvi==null) ? null : type;
+
+ // Now resolve the typename.
+ // There are some quibbles about algorithm; see comments on
+ // the resolve methods.
+ heavyResolveTypeName(psvi,member,type,isAttr);
+ }
+
+ /** Internal constructor to support getItemType and
+ * AbstractSchema.lookUpType
+ * @param psvi XNI Post-Schema-Validation Infoset annotation.
+ * @param isAttr True iff we're defining type for an attribute.
+ * */
+ public XPath2Type(XSTypeDefinition itemType, String namespace, String localName)
+ {
+ m_xniType=itemType;
+ m_namespace=namespace;
+ m_localName=localName;
+ }
+
+ /** Identity needs to be defined so we can do sparse storage.
+ * %REVIEW% I'm not sure all three fields need to be checked, but...
+ * */
+ public boolean equals(XPath2Type other)
+ {
+ // Could cache hashCode()'s result and use that to accelerate
+ // doesn't-equal testing at the cost of some storage and
+ // slowing down does-equal tests. Not convinced it's useful here.
+ // %REVIEW%
+ return (m_xniType==other.m_xniType ||
+ m_xniType!=null && m_xniType.equals(other.m_xniType)) &&
+ // These two won't be null
+ m_localName.equals(other.m_localName) &&
+ m_namespace.equals(other.m_namespace);
+ }
+
+ /** Identity needs to be defined so we can do sparse storage.
+ * %REVIEW% I'm not sure all three fields need to be checked, but...
+ * */
+ public int hashCode()
+ {
+ // Could cache hashCode(). See discussion in equals().
+ // %REVIEW%
+ return m_namespace.hashCode()+m_localName.hashCode()+
+ (m_xniType==null ? 0 : m_xniType.hashCode());
+ }
+
+ public String getTargetNamespace() {return m_namespace;}
+ public String getTypeName() {return m_localName;}
+
+ public boolean derivedFrom(String namespace,String localname)
+ {
+ if(m_xniType instanceof XSTypeDecl)
+ return ((XSTypeDecl)m_xniType).derivedFrom(namespace,localname);
+ else
+ {
+ // Fallback in case no PSVI info was passed in: exact match
+ // (it's got to be the correct xsi:any*Type).
+ return(m_localName.equals(localname) && m_namespace.equals(namespace));
+ }
+ }
+
+ /** Broken out into a subroutine so I can use it for debugging purposes.
+ * This logic is adapted from the Xerces SimpleTypeUsage.validateString() example.
+ *
+ * %REVIEW% May be more efficient to fold it back in.
+ *
+ * NOTE: Typed value depends on context information -- for example, a
+ * QName must be interpreted w/r/t a specific Namespace context. It's
+ * the caller's responisibility to pass down that information, since only
+ * the caller knows which context this operation is being performed in.
+ *
+ * %REVIEW% Currently NS context comes down as a SAX accessor. Should we be
+ * able to take a DTM node directly as context?
+ *
+ * @param textValue Text content to be interpreted
+ * @param nsctxt SAX namespace context, which will be proxied as XNI.
+ * @return DTM_XSequence containing one or more Java values, as appropriate
+ * to the Built-In Type we have inherited from -- or null if no such
+ * mapping exists (eg, if actualType was complex)
+ * */
+ public DTMSequence typedValue(String textvalue, org.xml.sax.helpers.NamespaceSupport nsctxt)
+ {
+ Object value;
+ DTM_XSequence seq=null;
+
+ if(m_xniType instanceof XSSimpleTypeDefinition)
+ {
+ //create an instance of 'ValidatedInfo' to get back information
+ //(like actual value, normalizedValue etc..)after content is validated.
+ ValidatedInfo validatedInfo = new ValidatedInfo(); // %REVIEW% Can we reuse???
+
+ //get proper validation context. This is very important, since
+ // it's where we get data for resolving prefixes (in QNames),
+ // known IDs (for IDREFs and ID conflicts), entities, etc.
+ //Validation context passed is generally different while
+ // validating content and creating simple type (applyFacets)
+ ValidationState validationState = new ValidationState();
+ if(nsctxt!=null)
+ validationState.setNamespaceSupport(new XPath2NamespaceSupport(nsctxt));
+
+ // This may need to be bound to additional data using:
+ //validationState.setSymbolTable(....);
+ //validationState.setFacetChecking(...);
+ //validationState.setExtraChecking(...);
+
+ // Validate and parse the string
+ try{
+ ((XSSimpleTypeDecl)m_xniType).validate(textvalue, validationState, validatedInfo);
+ } catch(InvalidDatatypeValueException ex){
+ // %REVIEW% Won't happen in prototype, where I'm only revalidating
+ // existing data. _WILL_ happen in production, when we start generating
+ // new typed data. Needs to be handled better at that time...
+ System.err.println(ex.getMessage());
+ ex.printStackTrace(System.err);
+ }
+
+ //now 'validatedInfo' object contains information
+
+ // for number types (decimal, double, float, and types derived from them),
+ // Object return is BigDecimal, Double, Float respectively.
+ // Boolean is handled similarly.
+ // Some types (string and derived) just return the string itself.
+ value = validatedInfo.actualValue;
+
+ //The normalized value of a string type
+ // (Should we check for stings and return this instead?)
+ String normalizedValue = validatedInfo.normalizedValue ;
+
+ // If the type is a union type, then the member type which
+ // actually validated the string value will be:
+ // XSSimpleType memberType = validatedInfo.memberType ;
+
+ // %REVIEW% I presume this handles lists by returning arrays...?
+
+ seq=new DTM_XSequence(value,this);
+ }
+
+ return seq==null ? DTMSequence.EMPTY : seq;
+ }
+
+ /** @return individual element type, if this is a list-of; else null.
+ * %REVIEW% -- else self?
+ * */
+ public XPath2Type getItemType()
+ {
+ if(m_xniType instanceof XSSimpleTypeDefinition)
+ {
+ XSTypeDefinition itemType=((XSSimpleTypeDefinition)m_xniType).getItemType();
+ if(itemType!=null)
+ return new XPath2Type(
+ itemType,
+ m_xniType.getNamespace(),
+ m_xniType.getName());
+ }
+ return null;
+ }
+
+ /** Implementation of the XPath2 type-name resolution algorithm
+ * (data model 3.5).
+ *
+ * Code donated by Sandy Gao, using the new
+ * Heavy-Weight PSVI interfaces.
+ * Fractionated to deal with validity and type info not being
+ * simultaneously available in current Xerces.
+ *
+ * @param psvi the psvi information for the current node
+ * @param attr false for element (fallback is xs:anyType)
+ * true for attribute (fallback is xs:anySimpleType)
+ * */
+ protected void heavyResolveTypeName(ItemPSVI psvi, XSSimpleTypeDefinition member, XSTypeDefinition type, boolean attr)
+ {
+ /* Not compatable with old light-weight schema APIs
+ */
+ // check whether the node is valid
+ if (psvi == null ||
+ psvi.getValidity() != ItemPSVI.VALIDITY_VALID) {
+ // if the node is not valid, then return xs:anyType
+ m_namespace = "http://www.w3.org/2001/XMLSchema";
+ m_localName = attr ? "anySimpleType" : "anyType";
+ return;
+ }
+
+ // try provided member type definition, and return its name
+ if (member != null) {
+ m_namespace = member.getNamespace();
+ m_localName = member.getName();
+ return;
+ }
+
+ // try provided type definition, and return its name
+ if (type != null) {
+ m_namespace = type.getNamespace();
+ m_localName = type.getName();
+ return;
+ }
+
+
+ // Member type definitions promised to be available;
+ // can't proceed to check names independently
+
+ // all failed, return xs:anyType
+ m_namespace = "http://www.w3.org/2001/XMLSchema";
+ m_localName = attr ? "anySimpleType" : "anyType";
+ return;
+ // throw new java.lang.UnsupportedOperationException("Xerces Heavyweight PSVI not yet avaialble"); /**/
+ }
+
+ /** Implementation of the XPath2 type-name resolution algorithm
+ * (data model 3.5).
+ *
+ * Code donated by Sandy Gao, using the new
+ * Heavy-Weight PSVI interfaces
+ * This one works *ONLY* if type and validity are all known in the same
+ * PSVI, which is not the case in current Xerces.
+ *
+ * @param psvi the psvi information for the current node
+ * @param attr false for element (fallback is xs:anyType)
+ * true for attribute (fallback is xs:anySimpleType)
+ * */
+ protected void heavyResolveTypeName(ItemPSVI psvi, boolean attr)
+ {
+ heavyResolveTypeName(psvi,psvi.getMemberTypeDefinition(),
+ psvi.getTypeDefinition(), attr);
+ }
+
+ /** Modification of the XPath2 type-name resolution algorithm
+ * to reflect Sandy Gao's concerns about the official version
+ * not tolerating processors that implement the "lightweight" version
+ * of PSVI.
+ *
+ * Code donated by Sandy Gao, using the new
+ * Heavy-Weight PSVI interfaces
+ *
+ * @param psvi the psvi information for the current node
+ * @param attr false for element (fallback is xs:anyType)
+ * true for attribute (fallback is xs:anySimpleType)
+ * */
+ protected void proposedHeavyResolveTypeName(ItemPSVI psvi, boolean attr)
+ {
+ /* Not compatable with old light-weight schema APIs
+ */
+
+ // NAME OF THIS CONSTANT IS IN FLUX
+ int VALID=ItemPSVI.VALIDITY_VALID;
+ //int VALID=ItemPSVI.VALID_VALIDITY;
+
+ // check whether the node is valid
+ if (psvi == null ||
+ psvi.getValidity() != VALID) {
+ // if the node is not valid, then return xs:anyType
+ m_namespace = "http://www.w3.org/2001/XMLSchema";
+ m_localName = attr ? "anySimpleType" : "anyType";
+ return;
+ }
+
+ // try to get the member type definition, and return its name
+ XSSimpleTypeDefinition member = psvi.getMemberTypeDefinition();
+ if (member != null && member.getName() != null) {
+ m_namespace = member.getNamespace();
+ m_localName = member.getName();
+ return;
+ }
+
+ // try to get the type definition, and return its name
+ XSTypeDefinition type = psvi.getTypeDefinition();
+ if (type != null && type.getName() != null) {
+ m_namespace = type.getNamespace();
+ m_localName = type.getName();
+ return;
+ }
+
+ // Member type definitions promised to be available;
+ // can't proceed to check names independently
+
+ // all failed, return xs:anyType
+ m_namespace = "http://www.w3.org/2001/XMLSchema";
+ m_localName = attr ? "anySimpleType" : "anyType";
+ return;
+ // throw new java.lang.UnsupportedOperationException("Xerces Heavyweight PSVI not yet avaialble"); /**/
+ }
+
+ /** Attempt to write a simplified version of the type resolution
+ * algorithm (data model 3.5) using only the Light-Weight PSVI
+ * interfaces previously supported in Xerces (which I believe will be
+ * phased out when heavyweight come into play).
+ *
+ * Based on code donated by Sandy Gao.
+ *
+ * @param psvi the psvi information for the current node
+ * @param ret a String array with size 2
+ * index 0 is used to return the namespace name;
+ * index 1 is used to return the local name.
+ * @param attr false for element (fallback is xs:anyType)
+ * true for attribute (fallback is xs:anySimpleType)
+ * */
+ protected void lightResolveTypeName(ItemPSVI psvi, boolean attr)
+ {
+ /* Not compatable with new heavy-weight schema APIs
+ //
+
+ int VALID=ItemPSVI.VALID_VALIDITY;
+
+ // check whether the node is valid
+ if (psvi == null ||
+ psvi.getValidity() != VALID) {
+ // if the node is not valid, then return xs:anyType
+ m_namespace = "http://www.w3.org/2001/XMLSchema";
+ m_localName = attr ? "anySimpleType" : "anyType";
+ return;
+ }
+
+ // Member type definitions promised NOT to be available;
+ // proceed to check names independently
+
+ // Need the second test, apparently
+ if (!psvi.isMemberTypeAnonymous() && null!=psvi.getMemberTypeName() ) {
+ m_namespace = psvi.getMemberTypeNamespace();
+ m_localName = psvi.getMemberTypeName();
+ return;
+ }
+
+ // Need the second test, apparently
+ if (!psvi.isTypeAnonymous() && null!=psvi.getTypeName()) {
+ m_namespace = psvi.getTypeNamespace();
+ m_localName = psvi.getTypeName();
+ return;
+ }
+
+ // all failed, return xs:anyType
+ m_namespace = "http://www.w3.org/2001/XMLSchema";
+ m_localName = attr ? "anySimpleType" : "anyType";
+ return;
+ */ throw new java.lang.UnsupportedOperationException("Xerces Lightweight PSVI phased out"); /**/
+ }
+
+
+ //---------------------------------------------------------------------
+ /** Bridge from Xalan/SAX namespace context to XNI namespace context
+ */
+ class XPath2NamespaceSupport
+ extends org.apache.xerces.util.NamespaceSupport
+ {
+ org.xml.sax.helpers.NamespaceSupport saxNamespaceSupport;
+
+ /** Default constructor, not useful in this wrapper. */
+ public XPath2NamespaceSupport() {
+ throw new UnsupportedOperationException("Wrong c'tor call");
+ } // <init>()
+
+ /**
+ * Constructs a namespace context object and initializes it with
+ * the prefixes declared in the specified context. Not useful in this
+ * wrapper.
+ */
+ public XPath2NamespaceSupport(org.apache.xerces.xni.NamespaceContext context) {
+ throw new UnsupportedOperationException("Wrong c'tor call");
+ } // <init>(xni.NamespaceContext)
+
+ /**
+ * Constructs a namespace context object and initializes it with
+ * a SAX NamespaceSupport object. Use this c'tor.
+ * */
+ public XPath2NamespaceSupport(org.xml.sax.helpers.NamespaceSupport saxNS) {
+ saxNamespaceSupport=saxNS;
+ } // <init>(sax.helpers.NamespaceSupport)
+
+ //
+ // Public methods
+ //
+
+ // context management
+
+ /**
+ * Reset this Namespace support object for reuse.
+ *
+ * <p>It is necessary to invoke this method before reusing the
+ * Namespace support object for a new session.</p>
+ */
+ public void reset(org.apache.xerces.util.SymbolTable symbolTable) {
+ // no-op
+ } // reset(SymbolTable)
+
+ /**
+ * Start a new Namespace context.
+ * <p>
+ * Normally, you should push a new context at the beginning
+ * of each XML element: the new context will automatically inherit
+ * the declarations of its parent context, but it will also keep
+ * track of which declarations were made within this context.
+ * <p>
+ * The Namespace support object always starts with a base context
+ * already in force: in this context, only the "xml" prefix is
+ * declared.
+ *
+ * @see #popContext
+ */
+ public void pushContext() {
+ // I don't know if this will ever be used during validation...
+ saxNamespaceSupport.pushContext();
+ } // pushContext()
+
+
+ /**
+ * Revert to the previous Namespace context.
+ * <p>
+ * Normally, you should pop the context at the end of each
+ * XML element. After popping the context, all Namespace prefix
+ * mappings that were previously in force are restored.
+ * <p>
+ * You must not attempt to declare additional Namespace
+ * prefixes after popping a context, unless you push another
+ * context first.
+ *
+ * @see #pushContext
+ */
+ public void popContext() {
+ // I don't know if this will ever be used during validation...
+ saxNamespaceSupport.popContext();
+ } // popContext()
+
+ // operations within a context.
+
+ /**
+ * Declare a Namespace prefix.
+ * <p>
+ * This method declares a prefix in the current Namespace
+ * context; the prefix will remain in force until this context
+ * is popped, unless it is shadowed in a descendant context.
+ * <p>
+ * To declare a default Namespace, use the empty string. The
+ * prefix must not be "xml" or "xmlns".
+ * <p>
+ * Note that you must <em>not</em> declare a prefix after
+ * you've pushed and popped another Namespace.
+ *
+ * @param prefix The prefix to declare, or null for the empty
+ * string.
+ * @param uri The Namespace URI to associate with the prefix.
+ *
+ * @return true if the prefix was legal, false otherwise
+ *
+ * @see #getURI
+ * @see #getDeclaredPrefixAt
+ */
+ public boolean declarePrefix(String prefix, String uri) {
+ // I don't know if this will ever be used during validation...
+ return saxNamespaceSupport.declarePrefix(prefix,uri);
+ } // declarePrefix(String,String):boolean
+
+ /**
+ * Look up a prefix and get the currently-mapped Namespace URI.
+ * <p>
+ * This method looks up the prefix in the current context.
+ * Use the empty string ("") for the default Namespace.
+ *
+ * @param prefix The prefix to look up.
+ *
+ * @return The associated Namespace URI, or null if the prefix
+ * is undeclared in this context.
+ *
+ * @see #getDeclaredPrefixAt
+ */
+ public String getURI(String prefix) {
+ return saxNamespaceSupport.getURI(prefix);
+ } // getURI(String):String
+
+
+
+ /**
+ * Look up a namespace URI and get one of the mapped prefix.
+ * <p>
+ * This method looks up the namespace URI in the current context.
+ *
+ * @param uri The namespace URI to look up.
+ *
+ * @return one of the associated prefixes, or null if the uri
+ * does not map to any prefix.
+ *
+ * @see #getPrefix
+ */
+ public String getPrefix(String uri) {
+ return saxNamespaceSupport.getPrefix(uri);
+ } // getURI(String):String
+
+
+ /**
+ * Return a count of all prefixes currently declared, including
+ * the default prefix if bound.
+ */
+ public int getDeclaredPrefixCount() {
+ java.util.Enumeration e=saxNamespaceSupport.getDeclaredPrefixes();
+ int count=0;
+ while(e.hasMoreElements())
+ {
+ ++count;
+ e.nextElement();
+ }
+ return count;
+ } // getDeclaredPrefixCount():int
+
+ /**
+ * Returns the prefix at the specified index in the current context.
+ * %REVIEW% Massively inefficient in this implementation.
+ */
+ public String getDeclaredPrefixAt(int index) {
+ java.util.Enumeration e=saxNamespaceSupport.getDeclaredPrefixes();
+ String result=null;
+ for(; index>=0;--index)
+ {
+ if(e.hasMoreElements())
+ result=(String)e.nextElement();
+ else
+ return null;
+ }
+ return result;
+ } // getDeclaredPrefixAt(int):String
+
+ /**
+ * Returns the parent namespace context or null if there is no
+ * parent context. The total depth of the namespace contexts
+ * matches the element depth in the document.
+ * <p>
+ * <strong>Note:</strong> This method <em>may</em> return the same
+ * NamespaceContext object reference. The caller is responsible for
+ * saving the declared prefix mappings before calling this method.
+ */
+ public NamespaceContext getParentContext() {
+ // I suppose I could construct a new XPath2NamespaceSupport
+ // wrapped around the SAX parent context. I'd rather not
+ // unless I must.
+ throw new UnsupportedOperationException("Not supported; involves further crossing XNI/SAX boundaries");
+ } // getParentContext():NamespaceContext
+
+ } // class XPath2NamespaceSupport
+
+} // XPath2Type
+
diff --git a/src/org/apache/xml/utils/CharacterBlockEnumeration.java b/src/org/apache/xml/utils/CharacterBlockEnumeration.java
new file mode 100644
index 0000000..9e5872d
--- /dev/null
+++ b/src/org/apache/xml/utils/CharacterBlockEnumeration.java
@@ -0,0 +1,253 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.xml.utils;
+
+/** CharacterBlockEnumeration yields a series of {char[], int, int} triplets.
+ * Its primary use is returning a low-level representation of text scattered
+ * across multiple storage units, eg one or more FastStringBuffer "chunks",
+ * so they can be processed without first converting them to a single Java
+ * String or StringBuffer.
+ *
+ * Note that the values are displayed on this object rather than being
+ * returned as elements as in the standard Java Enumeration
+ * When constructed, the CharacterBlockEnumeration will immediately
+ * display the first available set of values; hasMoreElements() can be
+ * used to test whether another set is available, and nextElement() can
+ * be used to step to the next set.
+ *
+ * This class directly implements the basic functionality for a single
+ * string or character array; it can be subclassed to handle non-contiguous
+ * types such as FastStringBuffer. Obviously, in those cases it is the user's
+ * responsibility not to alter the data structure while it is being
+ * enumerated, except in ways that may (or may not) be explicitly permitted
+ * by those specific implementation classes. Even for this simple version,
+ * alterations to the source after enumeration begins are not guaranteed
+ * to be correctly reflected in the enumerated view.
+ *
+ * %REVIEW% An argument can be made for making this
+ * an interface. Since it's a transient, I'm not sure the extra fields
+ * are really enough of a nuisance to justify doing so.
+ * */
+public class CharacterBlockEnumeration
+// implements java.util.Enumeration, but see nextElement's comments
+{
+ protected char[] _chars=null;
+ protected int _start;
+ protected int _length;
+ protected String _string=null;
+
+ static final protected char[] EMPTY=new char[0];
+
+ /** Create an empty enumeration. */
+ public CharacterBlockEnumeration()
+ {
+ }
+
+ /** Construct a CharacterBlockEnumeration to represent the content
+ * of a Java string.
+ *
+ * @param s The String whose content is to be returned.
+ * */
+ public CharacterBlockEnumeration(String s)
+ {
+ _string=s;
+ _length=s.length();
+ }
+
+ /** Construct a CharacterBlockEnumeration to represent part of the content
+ * of a Java string.
+ *
+ * @param s The String whose content is to be returned.
+ * @param start Starting offset of the substring. If greater than
+ * or equal to the length of the string, we will deliver zero characters
+ * @param length Number of characters in the substring. This will be
+ * truncated to not exceed the length of the string.
+ * */
+ public CharacterBlockEnumeration(String s, int start, int length)
+ {
+ _string=s;
+ int l=s.length();
+ if(start<=l)
+ {
+ _start=start;
+ int max=l-start;
+ _length=(length<max) ? length : max;
+ }
+ }
+
+ /** Construct a CharacterBlockEnumeration to represent the content
+ * of a Java character array
+ *
+ * @param ch The char array whose content is to be returned.
+ * */
+ public CharacterBlockEnumeration(char[] ch)
+ {
+ _chars=ch;
+ _length=ch.length;
+ }
+
+
+ /** Construct a CharacterBlockEnumeration to represent part of the content
+ * of a Java character array
+ *
+ * @param ch The char array whose content is to be returned.
+ * @param start Starting offset of the substring. If greater than
+ * or equal to the length of the array, we will deliver zero characters
+ * @param length Number of characters in the substring. This will be
+ * truncated to not exceed the length of the array.
+ * */
+ public CharacterBlockEnumeration(char[] ch, int start, int length)
+ {
+ _chars=ch;
+ int l=ch.length;
+ if(start<=l)
+ {
+ _start=start;
+ int max=l-start;
+ _length=(length<max) ? length : max;
+ }
+ }
+
+ /** @return true if another character block can be accessed by calling
+ * nextElement()
+ */
+ public boolean hasMoreElements()
+ {
+ return false;
+ }
+
+ /** Advance to the next character block.
+ *
+ * @returns either this CharacterBlockEnumeration object (as a
+ * transient accessor to the "element") or null if no more elements are available.
+ * This is a bit of a kluge, but it allows us to claim that we
+ * implement the Java Enumeration interface if we want to do so, and
+ * it seems to be as good or bad as any other return value.
+ * */
+ public Object nextElement()
+ {
+ _chars=null;
+ _string=null;
+ return null;
+ }
+
+
+ /** @return the starting offset in the current block's character array
+ * */
+ public int getStart()
+ {
+ return _start;
+ }
+
+ /** @return the length of the the current block
+ * */
+ public int getLength()
+ {
+ return _length;
+ }
+
+ /**
+ * @return the current block's character array. Data will begin at
+ * offset {start}.
+ * */
+ public char[] getChars()
+ {
+ // Implementation note for this particular version of the class:
+ // In a JVM which optimizes String.toCharArray() by deferring
+ // dissociation of the array from the String (sharing storage until
+ // and unless the user attempts to modify the array), this may be
+ // significantly faster than the version which returns the selected
+ // characters into a user-supplied array. In others, it may be
+ // significantly slower.
+
+ if(_chars==null)
+ {
+ if(_string!=null)
+ _chars=_string.toCharArray();
+ else
+ _chars=EMPTY;
+ }
+ return _chars;
+ }
+
+ /** @param target A char[] to be copied into. If a buffer is not supplied
+ * we will create one.
+ *
+ * @param targetStart Offset in the target at which copying should begin.
+ *
+ * @return the buffer, filled with {length} characters starting at offset
+ * {targetStart}. Characters before or after that block should be unaffected.
+ * */
+ public char[] getChars(char[] target, int targetStart)
+ {
+ // See performance issues discussion above. But note that they
+ // apply only to this version of the class, not necessarily to
+ // subclasses such as the FSB version.
+ if(target==null)
+ target=new char[targetStart+_length];
+
+ if(_chars==null)
+ _string.getChars(_start,_start+_length,
+ target,targetStart);
+ else
+ System.arraycopy(_chars,_start,target,targetStart,_length);
+
+ return target;
+ }
+
+}
+
diff --git a/src/org/apache/xml/utils/DateTimeObj.java b/src/org/apache/xml/utils/DateTimeObj.java
new file mode 100644
index 0000000..061c148
--- /dev/null
+++ b/src/org/apache/xml/utils/DateTimeObj.java
@@ -0,0 +1,1101 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.xml.utils;
+
+
+import java.text.DecimalFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import javax.xml.transform.TransformerException;
+import org.apache.xml.dtm.XType;
+
+/**
+ * <meta name="usage" content="general"/>
+ * This class contains a duration object.
+ */
+
+public class DateTimeObj
+{
+ // Datetime formats (era and zone handled separately).
+ public static final String dt1 = "yyyy-MM-dd'T'HH:mm:ss.ss";
+ public static final String dt2 = "yyyy-MM-dd'T'HH:mm:ss";
+ public static final String d = "yyyy-MM-dd";
+ public static final String gym = "yyyy-MM";
+ public static final String gy = "yyyy";
+ public static final String gmd = "MM-dd";
+ public static final String gm = "MM";
+ public static final String gd = "dd";
+ public static final String t1 = "HH:mm:ss.ss";
+ public static final String t2 = "HH:mm:ss";
+
+ private int m_year;
+ private int m_month;
+ private int m_day;
+ private int m_T;
+ private int m_hour;
+ private int m_minute;
+ private double m_second;
+ private String m_zone;
+ private Date m_date;
+ private String m_dateTime;
+ private int m_size;
+ private boolean m_signed = false;
+
+ /**
+ * The duration string must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnD, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public DateTimeObj(String dateTimeIn) throws TransformerException
+ {
+ this(dateTimeIn, new String[]{dt2});
+ }
+
+ public DateTimeObj(String dateTimeIn, String[] formatsIn) throws TransformerException
+ {
+ try {
+
+ int i;
+
+ m_size = dateTimeIn.length();
+ // Remember our Time separator
+ m_T = (i = dateTimeIn.indexOf("T")) != -1 ? i : m_size ;
+ // boundary check??
+ String[] edz = getEraDatetimeZone(dateTimeIn);
+ m_signed = edz[0].length() >0;
+ m_dateTime = edz[1];
+ m_zone = edz[2];
+ if (m_dateTime == null || m_zone == null)
+ return;
+
+ m_date = testFormats(m_dateTime, formatsIn);
+ int index = dateTimeIn.indexOf('.');
+ double dec = (index <0) ? 0 :Double.parseDouble(m_dateTime.substring(index));
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat(dt1);
+ dateFormat.setLenient(false);
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(m_date);
+ m_year = cal.get(Calendar.YEAR);
+ m_month = cal.get(Calendar.MONTH) + 1; // Calendar returns months starting at 0...
+ m_day = cal.get(Calendar.DATE);
+ m_hour = cal.get(Calendar.HOUR);
+ m_minute = cal.get(Calendar.MINUTE);
+ m_second = (index <0) ? cal.get(Calendar.SECOND)
+ : cal.get(Calendar.SECOND) + Double.parseDouble(m_dateTime.substring(index));
+ }
+ catch (Exception ex)
+ {
+ throw new TransformerException(ex);
+ }
+
+ }
+
+ public DateTimeObj(Date date, String formatOut) throws TransformerException
+ {
+ //m_zone = date.getTimezoneOffset();
+ SimpleDateFormat dateFormat = new SimpleDateFormat(formatOut);
+ dateFormat.setLenient(false);
+ m_dateTime = dateFormat.format(date);
+ m_date = date;
+
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(date);
+
+ m_signed = (cal.get(Calendar.ERA) == GregorianCalendar.BC);
+ m_year = cal.get(Calendar.YEAR);
+ // String monthStr = m_dateTime.substring(5, 7);
+ // m_month = Integer.valueOf(monthStr).intValue();
+ // String dayStr = m_dateTime.substring(8, 10);
+ // m_day = Integer.valueOf(dayStr).intValue();
+ m_month = cal.get(Calendar.MONTH) + 1;
+ m_day = cal.get(Calendar.DATE);
+ m_hour = cal.get(Calendar.HOUR);
+ m_minute = cal.get(Calendar.MINUTE);
+ m_second = cal.get(Calendar.SECOND);
+
+ // m_year = date.getYear();
+ // m_month = date.getMonth();
+ // m_day = date.getDay();
+ // m_hour = date.getHours();
+ // m_minute = date.getMinutes();
+ // m_second = date.getSeconds();
+ }
+
+ /** Added by JJK to support Xerces' stopgap internal representation
+ * as delivered through DTMSequence. We should work with them to
+ * converge on a shared time/date/duration object compatable with
+ * the schema spec.
+ *
+ * %BUG% They return some bogus fields due to normalization
+ * side-effects (they use a pseudodate of 2000/1/15 or something
+ * like that). To fix that we need to check the schema-type
+ * and ignore those fields...
+ *
+ * %BUG% No idea what format I should be using for m_dateTime!
+ * */
+ public DateTimeObj(int[] xercesdate,String typeLocalName)
+ {
+ try
+ {
+ m_year = Math.abs(xercesdate[0]);
+ m_month = xercesdate[1];
+ m_day = xercesdate[2];
+ m_hour = xercesdate[3];
+ m_minute = xercesdate[4];
+ m_second = xercesdate[5]+(xercesdate[6]/1000);
+ //m_zone = xercesdate[6]; // not sure how encoded
+
+ m_signed = (xercesdate[0] < 0);
+
+ /* Works, but gives slightly different results. Need to
+ * investigate...
+ int type = XType.getTypeFromLocalName(typeLocalName);
+ String format;
+ switch (type)
+ {
+ case XType.DATE:
+ format = d;
+ break;
+ case XType.TIME:
+ format = t1;
+ break;
+ default:
+ format = dt1;
+ }
+ Calendar cal = Calendar.getInstance();
+ cal.set(m_year,(m_month-1),m_day,m_hour,m_minute,(int)m_second);
+
+ m_date = cal.getTime();
+ SimpleDateFormat dateFormat = new SimpleDateFormat(format);
+ dateFormat.setLenient(false);
+ m_dateTime = dateFormat.format(m_date);
+ */
+
+ // Don't particularly like constructing this string,
+ // but will do for now. Need to investigate why Date or
+ // Calendar don't work here...
+
+ m_dateTime = formatYears(m_year) + "-" + formatDigits(m_month) + "-" + formatDigits(m_day);
+ // m_dateTime = m_year + "-" + m_month + "-" + m_day;
+ if (m_hour != 0 && m_minute != 0 && m_second != 0)
+ m_dateTime = m_dateTime + "T" + formatDigits(m_hour) + ":" + formatDigits(m_minute) + ":" + m_second;
+ String[] formatsIn = {dt2, d, t2};
+ m_date = testFormats(m_dateTime, formatsIn);
+
+ if (m_signed)
+ m_dateTime = "-" + m_dateTime;
+
+ }
+ catch (Exception ex)
+ {
+ throw new WrappedRuntimeException(ex);
+ }
+
+
+ // This is wrong but I'm not sure what format I should be using!
+ //SimpleDateFormat dateFormat = new SimpleDateFormat();
+ //dateFormat.setLenient(false);
+ //m_dateTime=dateFormat.format(m_date);
+ }
+
+ /**
+ * Attempt to parse an input string with the allowed formats, returning
+ * null if none of the formats work. Input formats are passed in longest to shortest,
+ * so if any parse operation fails with a parse error in the string, can
+ * immediately return null.
+ */
+ private static Date testFormats (String in, String[] formats)
+ throws ParseException
+ {
+
+ for (int i = 0; i <formats.length; i++)
+ {
+ try
+ {
+ SimpleDateFormat dateFormat = new SimpleDateFormat(formats[i]);
+ dateFormat.setLenient(false);
+ return dateFormat.parse(in);
+ }
+ catch (ParseException pe)
+ {
+ if ( i == formats.length -1)
+ throw pe;
+ }
+
+ }
+ return null;
+
+ }
+
+ /**
+ * Returns an array with the 3 components that a datetime input string
+ * may contain: - (for BC era), datetime, and zone. If the zone is not
+ * valid, return null for that component.
+ */
+ private String[] getEraDatetimeZone(String in) throws TransformerException
+ {
+ String leader = "";
+ String datetime = in;
+ String zone = "";
+ if (in.charAt(0)=='-')
+ {
+ leader = "-"; // '+' is implicit , not allowed
+ datetime = in.substring(1);
+ }
+ int z = getZoneStart(datetime);
+ if (z > 0)
+ {
+ zone = datetime.substring(z);
+ datetime = datetime.substring(0, z);
+ }
+ else if (z == -2)
+ zone = null;
+ //System.out.println("'" + leader + "' " + datetime + " " + zone);
+ return new String[]{leader, datetime, zone};
+ }
+
+ /**
+ * Returns an array with the 3 components that a datetime input string
+ * may contain: - (for BC era), datetime, and zone. If the zone is not
+ * valid, return null for that component.
+ */
+ private Date normalizeDate(Date date, String zone)
+ {
+ if (zone == null || zone.length()==0 || zone.equals("Z") || zone.equals("00:00") )
+ return date;
+ else
+ {
+ int sign = 1;
+ if (zone.startsWith("-"))
+ {
+ sign = -1;
+ }
+ int index = zone.indexOf(":");
+ int hr = sign * (Integer.parseInt(zone.substring(1, index)));
+ int min = sign * (Integer.parseInt(zone.substring(index+1)));
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ cal.add(Calendar.HOUR, hr);
+ cal.add(Calendar.MINUTE, min);
+ return cal.getTime();
+ }
+ }
+
+ /**
+ * Get the start of zone information if the input ends
+ * with 'Z' or +/-hh:mm. If a zone string is not
+ * found, return -1; if the zone string is invalid,
+ * return -2.
+ */
+ private int getZoneStart (String datetime) throws TransformerException
+ {
+ if (datetime.indexOf("Z") == datetime.length()-1)
+ return datetime.indexOf("Z");
+ else if (
+ (datetime.lastIndexOf("-") == datetime.length()-6 &&
+ datetime.charAt(datetime.length()-3) == ':')
+ ||
+ (datetime.indexOf("+") == datetime.length() -6)
+ )
+ {
+ try
+ {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm");
+ dateFormat.setLenient(false);
+ Date d = dateFormat.parse(datetime.substring(datetime.length() -5));
+ return datetime.length()-6;
+ }
+ catch (ParseException pe)
+ {
+ throw new TransformerException(pe);
+ //return -2; // Invalid.
+ }
+
+ }
+ return -1; // No zone information.
+ }
+
+ /**
+ * See dateTime.
+ */
+ public static DateTimeObj date() throws TransformerException
+ {
+ return currentDateTime(d);
+ }
+
+
+ /**
+ * The date:date function returns the date specified in the date/time string given
+ * as the argument. If no argument is given, then the current local date/time, as
+ * returned by date:date-time is used as a default argument.
+ * The date/time string that's returned must be a string in the format defined as the
+ * lexical representation of xs:dateTime in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">[3.2.7 dateTime]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * If the argument is not in either of these formats, date:date returns an empty string ('').
+ * The date/time format is basically CCYY-MM-DDThh:mm:ss, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ * The date is returned as a string with a lexical representation as defined for xs:date in
+ * [3.2.9 date] of [XML Schema Part 2: Datatypes]. The date format is basically CCYY-MM-DD,
+ * although implementers should consult [XML Schema Part 2: Datatypes] and [ISO 8601] for details.
+ * If no argument is given or the argument date/time specifies a time zone, then the date string
+ * format must include a time zone, either a Z to indicate Coordinated Universal Time or a + or -
+ * followed by the difference between the difference from UTC represented as hh:mm. If an argument
+ * is specified and it does not specify a time zone, then the date string format must not include
+ * a time zone.
+ */
+ public static DateTimeObj date(String dateIn) throws TransformerException
+ {
+ DateTimeObj dt = new DateTimeObj (dateIn, new String[]{d});
+
+ return dt;
+ }
+
+
+ public static DateTimeObj date(Date dateIn) throws TransformerException
+ {
+ DateTimeObj dt = new DateTimeObj (dateIn, d);
+
+ return dt;
+ }
+
+
+ /**
+ * The date:time function returns the time specified in the time string given
+ * as the argument.
+ * The time string that's returned must be a string in the format defined as the
+ * lexical representation of xs:time in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#time">[3.2.7 time]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * If the argument string is not in this format, date:time returns an empty string ('').
+ * The time format is basically hh:mm:ss, although implementers should consult
+ * If no argument is given or the argument time specifies a time zone, then the time string
+ * format must include a time zone, the difference from UTC represented as hh:mm. If an argument
+ * is specified and it does not specify a time zone, then the time string format must not include
+ * a time zone.
+ */
+ public static DateTimeObj time() throws TransformerException
+ {
+ return currentDateTime(t1);
+ }
+
+
+ public static DateTimeObj time(String timeIn) throws TransformerException
+ {
+ DateTimeObj dt = new DateTimeObj (timeIn, new String[]{t1, t2});
+
+ return dt;
+ }
+
+
+ public static DateTimeObj time(Date timeIn) throws TransformerException
+ {
+ DateTimeObj dt = new DateTimeObj (timeIn, t1);
+
+ return dt;
+ }
+
+
+ public static DateTimeObj gYearMonth(String dateIn) throws TransformerException
+ {
+ // Check on java g Date stuff...
+ DateTimeObj dt = new DateTimeObj (dateIn, new String[]{gym});
+
+ return dt;
+ }
+
+
+ public static DateTimeObj gYear(String dateIn) throws TransformerException
+ {
+ // Check on java g Date stuff...
+ DateTimeObj dt = new DateTimeObj (dateIn, new String[]{gy});
+
+ return dt;
+ }
+
+
+ public static DateTimeObj gMonth(String dateIn) throws TransformerException
+ {
+ // Check on java g Date stuff...
+ DateTimeObj dt = new DateTimeObj (dateIn, new String[]{gm});
+
+ return dt;
+ }
+
+ public static DateTimeObj gMonthDay(String dateIn) throws TransformerException
+ {
+ // Check on java g Date stuff...
+ DateTimeObj dt = new DateTimeObj (dateIn, new String[]{gmd});
+
+ return dt;
+ }
+
+
+ public static DateTimeObj gDay(String dateIn) throws TransformerException
+ {
+ // Check on java g Date stuff...
+ DateTimeObj dt = new DateTimeObj (dateIn, new String[]{gd});
+
+ return dt;
+ }
+
+
+ /**
+ * The date:date-time function returns the current date and time as a date/time string.
+ * The date/time string that's returned must be a string in the format defined as the
+ * lexical representation of xs:dateTime in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">[3.2.7 dateTime]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The date/time format is basically CCYY-MM-DDThh:mm:ss, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ * The date/time string format must include a time zone, either a Z to indicate Coordinated
+ * Universal Time or a + or - followed by the difference between the difference from UTC
+ * represented as hh:mm.
+ */
+ public static DateTimeObj currentDateTime(String pattern) throws TransformerException
+ {
+ Calendar cal = Calendar.getInstance();
+ Date datetime = cal.getTime();
+ DateTimeObj dt = new DateTimeObj(datetime, pattern);
+
+ int offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
+ // If there is no offset, we have "Coordinated
+ // Universal Time."
+ if (offset == 0)
+ dt.setZone("Z");
+ else
+ {
+ // Convert milliseconds to hours and minutes
+ int hrs = offset/(60*60*1000);
+ // In a few cases, the time zone may be +/-hh:30.
+ int min = offset%(60*60*1000);
+ char posneg = hrs < 0? '-': '+';
+ dt.setZone(posneg + formatDigits(hrs) + ':' + formatDigits(min));
+ }
+ return dt;
+ }
+
+
+ /**
+ * See above
+ */
+ public static DateTimeObj dateTime() throws TransformerException
+ {
+ return dateTime(dt1);
+ }
+
+
+ /**
+ * The date:date-time function returns the date and time specified in the date/time
+ * string given as the argument..
+ * The date/time string that's returned must be a string in the format defined as the
+ * lexical representation of xs:dateTime in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">[3.2.7 dateTime]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The date/time format is basically CCYY-MM-DDThh:mm:ss, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ * The date/time string format must include a time zone, either a Z to indicate Coordinated
+ * Universal Time or a + or - followed by the difference between the difference from UTC
+ * represented as hh:mm.
+ */
+ public static DateTimeObj dateTime(String dateTimeIn)
+ throws TransformerException
+ {
+ return new DateTimeObj(dateTimeIn);
+ }
+
+ /**
+ * Represent the hours and minutes with two-digit strings.
+ * @param q hrs or minutes.
+ * @return two-digit String representation of hrs or minutes.
+ */
+ private static String formatDigits(int q)
+ {
+ String dd = String.valueOf(Math.abs(q));
+ return dd.length() == 1 ? "0" + dd : dd;
+ }
+
+ /**
+ * Represent the hours and minutes with two-digit strings.
+ * @param q hrs or minutes.
+ * @return two-digit String representation of hrs or minutes.
+ */
+ private static String formatYears(int q)
+ {
+ String dd = String.valueOf(Math.abs(q));
+ int len = dd.length();
+ for (int i=len; i<4; i++)
+ dd = "0" + dd;
+ return dd;
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMn, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public Duration getYMDuration(DateTimeObj dt) throws TransformerException
+ {
+ Duration du = null;
+ double secs = new Long((m_date.getTime() - dt.m_date.getTime())/1000).doubleValue();
+
+ String sign = secs <0 ? "-" : "";
+ double days = Math.abs(((secs/60)/60)/24);
+ double months = days/31 + (days%31 <15.5 ? 0 : 1);
+ int monthDu = new Double(months%12).intValue();
+ int yearDu = new Double(months/12).intValue();
+
+ return new Duration(sign + "P" + (yearDu != 0 ? (Integer.toString(yearDu) + "Y") : "")
+ + (monthDu != 0 ? (Integer.toString(monthDu) + "M") : "") );
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMn, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public Duration getDTDuration(DateTimeObj dt) throws TransformerException
+ {
+ Duration du = null;
+ double secs = new Long((m_date.getTime() - dt.m_date.getTime())/1000).doubleValue();
+
+ String sign = secs <0 ? "-" : "";
+ secs = Math.abs(secs);
+ double secDu = secs%60;
+ int mins = (new Double(secs)).intValue()/60;
+ int mnDu = mins%60;
+ int hours = mins/60;
+ int hourDu = hours%24;
+ int dayDu = hours/24;
+
+ return new Duration(sign + "P" + (dayDu != 0 ? (Integer.toString(dayDu) + "D") : "")
+ + ((hourDu != 0 || mnDu != 0 || secDu != 0) ? "T" : "")
+ + (hourDu != 0 ? (Integer.toString(hourDu) + "H") : "")
+ + (mnDu != 0 ? (Integer.toString(mnDu) + "M") : "")
+ + (secDu != 0 ? (Double.toString(secDu) + "S") : "") );
+ }
+
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean lessThan(DateTimeObj dt)
+ {
+ if (m_zone.equals(dt.m_zone))
+ {
+ if( m_date.before(dt.m_date))
+ /*
+ if ((m_year < dt.m_year || (m_year == 0 && dt.m_year == 0)) &&
+ (m_month < dt.m_month || (m_month == 0 && dt.m_month == 0)) &&
+ (m_day < dt.m_day || (m_day ==0 && dt.m_day == 0)) &&
+ (m_hour < dt.m_hour || (m_hour == 0 && dt.m_hour == 0)) &&
+ (m_minute < m_minute || (m_minute == 0 && m_minute == 0)) &&
+ (m_second < dt.m_second || (m_second == 0 && dt.m_second == 0)) )
+ */
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ Date date1 = normalizeDate(m_date, m_zone);
+ Date date2 = normalizeDate(dt.m_date, dt.m_zone);
+ if (date1.before(date2))
+ return true;
+ else
+ return false;
+ }
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean lessThanOrEqual(DateTimeObj dt)
+ {
+ return (lessThan(dt) || equals(dt));
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean greaterThan(DateTimeObj dt)
+ {
+ return dt.lessThan(this);
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean greaterThanOrEqual(DateTimeObj dt)
+ {
+ return (greaterThan(dt) || equals(dt));
+ }
+
+
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean equals(DateTimeObj dt)
+ {
+ if (m_zone.equals(dt.m_zone))
+ {
+ if (m_year == dt.m_year &&
+ m_month == dt.m_month &&
+ m_day == dt.m_day &&
+ m_hour == dt.m_hour &&
+ m_minute == dt.m_minute &&
+ m_second == dt.m_second)
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ Date date1 = normalizeDate(m_date, m_zone);
+ Date date2 = normalizeDate(dt.m_date, dt.m_zone);
+ if (date1.before(date2) || date2.before(date1))
+ return false;
+ else
+ return true;
+ }
+ }
+
+
+ public DateTimeObj addDays(double days)
+ throws TransformerException
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(m_date);
+ cal.add(Calendar.DATE, new Double(days).intValue());
+
+ DateTimeObj dateTime = date(cal.getTime());
+ dateTime.setZone(m_zone);
+ return dateTime;
+
+ }
+
+
+
+ public DateTimeObj addYMDurationToDateTime(Duration d)
+ throws TransformerException
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(m_date);
+ int sign = (d.getSigned()) ? -1 : 1;
+ cal.add(Calendar.YEAR, sign * (d.getYears()));
+ cal.add(Calendar.MONTH, sign * (d.getMonths()));
+
+ DateTimeObj dateTime = new DateTimeObj(cal.getTime(), dt2 );
+ dateTime.setZone(m_zone);
+ return dateTime;
+
+ }
+
+ public DateTimeObj addYMDurationToDate(Duration d)
+ throws TransformerException
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(m_date);
+ int sign = (d.getSigned()) ? -1 : 1;
+ cal.add(Calendar.YEAR, sign * (d.getYears()));
+ cal.add(Calendar.MONTH, sign * (d.getMonths()));
+ DateTimeObj dt = date(cal.getTime());
+ dt.setZone(m_zone);
+ return dt;
+ }
+
+ public DateTimeObj subtractYMDurationFromDateTime(Duration d)
+ throws TransformerException
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(m_date);
+ int sign = (d.getSigned()) ? 1 : -1;
+ cal.add(Calendar.MONTH, sign * (d.getMonths() + (d.getYears() * 12)));
+
+ DateTimeObj dateTime = new DateTimeObj(cal.getTime(), dt1);
+ dateTime.setZone(m_zone);
+ return dateTime;
+
+ }
+
+ public DateTimeObj subtractYMDurationFromDate(Duration d)
+ throws TransformerException
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(m_date);
+ int sign = (d.getSigned()) ? 1 : -1;
+ cal.add(Calendar.MONTH, sign * (d.getMonths() + (d.getYears() * 12)));
+
+ DateTimeObj dt = date(cal.getTime());
+ dt.setZone(m_zone);
+ return dt;
+ }
+
+
+ public DateTimeObj addDTDurationToDateTime(Duration d)
+ throws TransformerException
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(m_date);
+ int sign = (d.getSigned()) ? -1 : 1;
+ double secs = d.getSeconds() + (((((d.getDays() * 24) + d.getHours()) * 60) + d.getMinutes()) * 60);
+ int intVal = new Double(secs).intValue();
+ cal.add(Calendar.SECOND , sign * intVal);
+
+ Date date = cal.getTime();
+ SimpleDateFormat dateFormat = new SimpleDateFormat(dt2);
+ dateFormat.setLenient(false);
+ String dateTime = dateFormat.format(date);
+ if (secs - intVal != 0)
+ {
+ String val = Double.toString(secs);
+ int index = val.indexOf('.');
+ dateTime = (index<0) ? dateTime : dateTime + val.substring(index);
+ }
+ //DateTimeObj dt = new DateTimeObj(cal.getTime(), dt2);
+ DateTimeObj dt = new DateTimeObj(dateTime);
+ dt.setZone(m_zone);
+ return dt;
+ }
+
+
+
+ public DateTimeObj addDTDurationToDate(Duration d)
+ throws TransformerException
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(m_date);
+ int sign = (d.getSigned()) ? -1 : 1;
+ cal.add(Calendar.MONTH, sign * (d.getMonths()));
+ cal.add(Calendar.DATE, sign * (d.getDays()));
+
+ DateTimeObj dt = date(cal.getTime());
+ dt.setZone(m_zone);
+ return dt;
+ }
+
+
+ public DateTimeObj addDTDurationToTime(Duration d)
+ throws TransformerException
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(m_date);
+ int sign = (d.getSigned()) ? -1 : 1;
+ double secs = d.getSeconds() + ((((d.getHours()) * 60) + d.getMinutes()) * 60);
+ int intVal = new Double(secs).intValue();
+ cal.add(Calendar.SECOND , sign * intVal);
+
+ Date date = cal.getTime();
+ SimpleDateFormat dateFormat = new SimpleDateFormat(t2);
+ dateFormat.setLenient(false);
+ String dateTime = dateFormat.format(date);
+ if (secs - intVal != 0)
+ {
+ String val = Double.toString(secs);
+ int index = val.indexOf('.');
+ dateTime = (index<0) ? dateTime : dateTime + val.substring(index);
+ }
+ DateTimeObj dt = time(dateTime);
+ dt.setZone(m_zone);
+ return dt;
+ }
+
+
+ public DateTimeObj subtractDTDurationFromDateTime(Duration d)
+ throws TransformerException
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(m_date);
+ int sign = (d.getSigned()) ? 1 : -1;
+ double secs = d.getSeconds() + (((((d.getDays() * 24) + d.getHours()) * 60) + d.getMinutes()) * 60);
+ cal.add(Calendar.SECOND , sign * (new Double (Math.floor(secs)).intValue()));
+
+ DateTimeObj dt = new DateTimeObj(cal.getTime(), dt1);
+ dt.setZone(m_zone);
+ return dt;
+ }
+
+ public DateTimeObj subtractDTDurationFromDate(Duration d)
+ throws TransformerException
+ {
+
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(m_date);
+ int sign = (d.getSigned()) ? 1 : -1;
+ // subtracting 1 from the number of days, because counting
+ // from end of given day, so it counts for day 1
+ // cal.add(Calendar.DATE, sign * (d.getDays()-1));
+ // "(date('2002-08-05')-duration('P42D'))+duration('P42D') = date('2002-08-05')"
+ // doesn't work if you do the -1. It sure feels like that is wrong.
+ // -sb
+ double secs = d.getSeconds() + (((((d.getDays() * 24) + d.getHours()) * 60) + d.getMinutes()) * 60);
+ cal.add(Calendar.SECOND , sign * (new Double (Math.floor(secs)).intValue()));
+
+ DateTimeObj dt = date(cal.getTime());
+ dt.setZone(m_zone);
+ return dt;
+ }
+
+ /**
+ * Method subtractDateFromDate.
+ * @param date2
+ * @return Duration
+ * @throws TransformerException
+ */
+ public Duration subtractDateFromDate(DateTimeObj date2)
+ throws TransformerException
+ {
+
+ /*Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(m_date);
+
+ int year = m_year - date2.m_year;
+ int month = m_month - date2.m_month;
+ int day = m_day - date2.m_day;
+ int hour = m_hour - date2.m_hour;
+ int minute = m_minute - date2.m_minute;
+ double second = m_second - date2.m_second;
+
+ Duration dur = new Duration(year, month, day, hour, minute, second);
+
+ return dur;*/
+ return getDTDuration(date2);
+ }
+
+
+
+ public DateTimeObj subtractDTDurationFromTime(Duration d)
+ throws TransformerException
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.setTime(m_date);
+ int sign = (d.getSigned()) ? 1 : -1;
+ double secs = d.getSeconds() + ((((d.getHours()) * 60) + d.getMinutes()) * 60);
+ cal.add(Calendar.SECOND , sign * (new Double(Math.floor(secs)).intValue()));
+
+ DateTimeObj dt = time(cal.getTime());
+ dt.setZone(m_zone);
+ return dt;
+ }
+
+
+
+ public void setYears(int years)
+ {
+ m_year = years;
+ }
+
+ public int getYears()
+ {
+ return m_year;
+ }
+
+ public void setMonths(int months)
+ {
+ m_month = months;
+ }
+
+ public int getMonths()
+ {
+ return m_month;
+ }
+
+ public void setDays(int days)
+ {
+ m_day = days;
+ }
+
+ public int getDays()
+ {
+ return m_day;
+ }
+
+ public void setHours(int hours)
+ {
+ m_hour = hours;
+ }
+
+ public int getHours()
+ {
+ return m_hour;
+ }
+
+ public void setSeconds(double secs)
+ {
+ m_second = secs;
+ }
+
+ public double getSeconds()
+ {
+ return m_second;
+ }
+
+ public void setMinutes(int mts)
+ {
+ m_minute = mts;
+ }
+
+ public int getMinutes()
+ {
+ return m_minute;
+ }
+
+ public void setZone(String zone)
+ {
+ m_zone = zone;
+ }
+
+ public String getZone()
+ {
+ if (m_zone.equals("Z") )
+ return ("00:00");
+ else
+ return m_zone;
+ }
+
+ public Date getDate()
+ {
+ return m_date;
+ }
+
+ public String toString()
+ {
+ return (m_dateTime + (m_zone == null ? "" : m_zone));
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/src/org/apache/xml/utils/DefaultErrorHandler.java b/src/org/apache/xml/utils/DefaultErrorHandler.java
index af40946..849fabe 100644
--- a/src/org/apache/xml/utils/DefaultErrorHandler.java
+++ b/src/org/apache/xml/utils/DefaultErrorHandler.java
@@ -60,10 +60,6 @@
import javax.xml.transform.ErrorListener;
import javax.xml.transform.TransformerException;
import javax.xml.transform.SourceLocator;
-
-import org.apache.xalan.res.XSLMessages;
-import org.apache.xalan.res.XSLTErrorResources;
-
import java.io.PrintWriter;
import java.io.PrintStream;
@@ -338,12 +334,12 @@
String id = (null != locator.getPublicId() )
? locator.getPublicId()
: (null != locator.getSystemId())
- ? locator.getSystemId() : XSLMessages.createMessage(XSLTErrorResources.ER_SYSTEMID_UNKNOWN, null); //"SystemId Unknown";
+ ? locator.getSystemId() : "SystemId Unknown";
- pw.print(id + "; " +XSLMessages.createMessage("line", null) + locator.getLineNumber()
- + "; " +XSLMessages.createMessage("column", null) + locator.getColumnNumber()+"; ");
+ pw.print(id + "; Line " + locator.getLineNumber()
+ + "; Column " + locator.getColumnNumber()+"; ");
}
else
- pw.print("("+XSLMessages.createMessage(XSLTErrorResources.ER_LOCATION_UNKNOWN, null)+")");
+ pw.print("(Location of error unknown)");
}
}
diff --git a/src/org/apache/xml/utils/Duration.java b/src/org/apache/xml/utils/Duration.java
new file mode 100644
index 0000000..23ef80c
--- /dev/null
+++ b/src/org/apache/xml/utils/Duration.java
@@ -0,0 +1,863 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.xml.utils;
+
+
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.Calendar;
+import java.text.SimpleDateFormat;
+import java.text.DateFormat;
+import java.text.ParseException;
+import javax.xml.transform.TransformerException;
+import org.apache.xpath.objects.XString;
+import org.apache.xpath.objects.XDouble;
+import org.apache.xpath.objects.XBoolean;
+import org.apache.xpath.objects.XObject;
+
+/**
+ * <meta name="usage" content="general"/>
+ * This class contains a duration object.
+ */
+
+public class Duration
+{
+
+ // Duration format
+ public static final String du = "PnYnMnDTnHnMn.nS";
+
+ private int m_year;
+ private int m_month;
+ private int m_day;
+ private static int m_T;
+ private int m_hour;
+ private int m_minute;
+ private double m_second;
+ private boolean m_signed;
+ private String m_sign = "-";
+ private String m_duration;
+ private int m_size;
+
+ /**
+ * The duration string must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnD, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public Duration(String duration) throws TransformerException
+ {
+ m_duration = duration;
+ int i;
+ m_size = duration.length();
+ m_signed = duration.startsWith("-");
+ int offset;
+ int start = offset = (m_signed ? 2 : 1); // Bypass the P
+ // Remember our Time separator
+ m_T = (i = duration.indexOf("T")) != -1 ? i : m_size ;
+ // boundary check??
+ // Maybe I can avoid doing string operations here if I will not need
+ // the individual values?? ie: int nY = ( (i = duration.indexOf("Y")) != -1) ? i - start : 0;
+ String nY = ( (i = duration.indexOf("Y")) != -1) ? duration.substring(start, i) :"";
+ start = (i > 0) ? (i + 1) : start ;
+ String nM = ((i = duration.substring(0,m_T).indexOf("M")) != -1 ) ? duration.substring(start, i) :"";
+ start = (i > 0) ? (i + 1) : start ;
+ String nD = ( (i = duration.indexOf("D")) != -1) ? duration.substring(start, i) :"";
+
+ try{
+ m_year = nY.length() >0 ? Integer.parseInt(nY) :0;
+ m_month = nM.length() >0 ? Integer.parseInt(nM) :0;
+ m_day = nD.length() >0 ? Integer.parseInt(nD) :0;
+
+ if (m_T < m_size)
+ {
+ start = (m_T < m_size) ? m_T + 1 : start;
+ String nH = ( (i = duration.indexOf("H")) != -1) ? duration.substring(start, i) :"";
+ start = (i > 0) ? (i + 1) : start ;
+ String nMt = ( (i = duration.substring(m_T, m_size).indexOf("M")) != -1) ? duration.substring(start, i+=m_T) :"";
+ start = (i > 0) ? (i + 1) : start ;
+ String nS = ( (i = duration.indexOf("S")) != -1) ? duration.substring(start, i) :"";
+
+ m_hour = nH.length() >0 ? Integer.parseInt(nH) :0;
+ m_minute = nMt.length() >0 ? Integer.parseInt(nMt) :0;
+ m_second = nS.length() >0 ? Double.valueOf(nS).doubleValue() :0;
+ }
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new TransformerException(nfe);
+ }
+
+ }
+
+ /** Added by JJK to support Xerces' stopgap internal representation
+ * as delivered through DTMSequence. We should work with them to
+ * converge on a shared time/date/duration object compatable with
+ * the schema spec.
+ * */
+ public Duration(int[] xercesduration)
+ {
+ // I'm not sure how they're representing negative durations!?
+ m_year = xercesduration[0];
+ m_month = xercesduration[1];
+ m_day = xercesduration[2];
+ m_hour = xercesduration[3];
+ m_minute = xercesduration[4];
+ m_second = xercesduration[5]+(xercesduration[6]/1000);
+ // xercesduration[8] is timezone related; ignore it.
+ }
+
+ public Duration(int year, int month, int day, int hour, int minute, double second)
+ {
+ // I'm not sure how they're representing negative durations!?
+ m_year = year;
+ m_month = month;
+ m_day = day;
+ m_hour = hour;
+ m_minute = minute;
+ m_second = second;
+
+ if(year < 0)
+ m_signed = true;
+ // xercesduration[8] is timezone related; ignore it.
+ }
+
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public static Duration duration(Duration du)
+ {
+ //Duration du = new Duration (duration);
+ int len = du.m_size;
+
+ if (!du.m_duration.startsWith("P", (du.m_signed ? 1 : 0)) ||
+ (du.m_year == 0 && du.m_month == 0 && du.m_day == 0 && du.m_hour == 0 && du.m_minute == 0 && du.m_second == 0) ||
+ (m_T == len && (du.m_hour != 0 || du.m_minute != 0 || du.m_second != 0)) ||
+ m_T == len -1)
+ return null;
+
+ return du;
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMn, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public static Duration YMDuration(String duration) throws TransformerException
+ {
+ Duration du = duration(new Duration (duration));
+ if (du == null)
+ return null;
+
+ if (!duration.startsWith("P", (du.m_signed ? 1 : 0)) ||
+ (du.m_day != 0 || du.m_hour != 0 || du.m_minute != 0 || du.m_second != 0) ||
+ (du.m_year == 0 && du.m_month == 0) )
+ return null;
+
+ return du;
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMn, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public static Duration YMDurationFromMonths(int months) throws TransformerException
+ {
+ String sign = (months > 0) ? "" : "-";
+ months = Math.abs(months);
+ int monthDu = months%12;
+ int yearDu = months/12;
+ return new Duration ( sign + "P" + (yearDu != 0 ? (Integer.toString(yearDu) + "Y") : "") + (monthDu != 0 ? (Integer.toString(monthDu) + "M") : ""));
+
+ }
+
+ public static Duration DTDuration(String duration) throws TransformerException
+ {
+ Duration du = duration(new Duration (duration));
+
+ if (!duration.startsWith("P", (du.m_signed ? 1 : 0)) ||
+ (du.m_year != 0 || du.m_month != 0) ||
+ (du.m_day == 0 && du.m_hour == 0 && du.m_minute == 0 && du.m_second == 0) )
+ return null;
+
+ return du;
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMn, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public static Duration DTDurationFromSecs(double secs) throws TransformerException
+ {
+ String sign = (secs > 0) ? "" : "-";
+ secs = Math.abs(secs);
+ double secDu = secs%60;
+ int mins = (new Double(secs)).intValue()/60;
+ int mnDu = mins%60;
+ int hours = mins/60;
+ int hourDu = hours%24;
+ int dayDu = hours/24;
+ return new Duration ( sign + "P"
+ + (dayDu != 0 ? (Integer.toString(dayDu) + "D") : "")
+ + ((hourDu != 0 || mnDu != 0 || secDu != 0) ? "T" : "")
+ + (hourDu != 0 ? (Integer.toString(hourDu) + "H") : "")
+ + (mnDu != 0 ? (Integer.toString(mnDu) + "M") : "")
+ + (secDu != 0 ? (Double.toString(secDu) + "S") : "") );
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean DTEqual(Duration du)
+ {
+ if ((m_signed == du.m_signed) &&
+ m_day == du.m_day &&
+ m_hour == du.m_hour &&
+ m_minute == du.m_minute &&
+ m_second == du.m_second)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean DTLessThan(Duration du)
+ {
+ int sign = (m_signed) ? -1 : 1;
+ int hrs = m_hour + (m_day * 24);
+ int mns = m_minute + (hrs * 60);
+ double secs = (m_second + (mns * 60)) * sign;
+
+ sign = (du.m_signed) ? -1 : 1;
+ hrs = du.m_hour + (du.m_day * 24);
+ mns = du.m_minute + (hrs * 60);
+ double secs2 = (du.m_second + (mns * 60)) * sign;
+
+
+ if (secs < secs2)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean DTLessThanOrEqual(Duration du)
+ {
+
+ return (DTLessThan(du) || DTEqual(du));
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean DTGreaterThan(Duration du)
+ {
+ return du.DTLessThan(this);
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean DTGreaterThanOrEqual(Duration du)
+ {
+
+ return (DTGreaterThan(du) || DTEqual(du));
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean YMEqual(Duration du)
+ {
+ if ((m_signed == du.m_signed) &&
+ m_year == du.m_year &&
+ m_month == du.m_month)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean YMLessThan(Duration du)
+ {
+ int sign = (m_signed) ? -1 : 1;
+ int months = (m_month + (m_year * 12)) * sign;
+
+ sign = (du.m_signed) ? -1 : 1;
+ int months2 = (du.m_month + (du.m_year * 12)) * sign;
+
+ if (months < months2)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean YMLessThanOrEqual(Duration du)
+ {
+
+ return (YMLessThan(du) || YMEqual(du));
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean YMGreaterThan(Duration du)
+ {
+ return du.YMLessThan(this);
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean YMGreaterThanOrEqual(Duration du)
+ {
+
+ return (YMGreaterThan(du) || YMEqual(du));
+ }
+
+ /**
+ * The duration function returns the duration specified in the duration
+ * string given as the argument..
+ * The duration string that's returned must be a string in the format defined as the
+ * lexical representation of xs:duration in
+ * <a href="http://www.w3.org/TR/xmlschema-2/#duration">[3.2.6 duration]</a> of
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
+ * The duration format is basically PnYnMnDTnHnMnS, although implementers should consult
+ * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and
+ * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
+ */
+ public boolean equals(Duration du)
+ {
+ if ((m_signed == du.m_signed) &&
+ m_year == du.m_year &&
+ m_month == du.m_month &&
+ m_day == du.m_day &&
+ m_hour == du.m_hour &&
+ m_minute == du.m_minute &&
+ m_second == du.m_second)
+ return true;
+ else
+ return false;
+ }
+
+
+
+ public Duration addYMDuration(Duration d)
+ throws TransformerException
+ {
+
+ String sign;
+ int monthDu, yearDu;
+ if (m_signed == d.m_signed) //!signed1 && !signed1 || signed1 && signed2)
+ {
+ sign = (m_signed) ? m_sign : "";
+ int months = m_month + d.m_month;
+ monthDu = months%12;
+ yearDu = months/12 + m_year + d.m_year;
+ }
+ else
+ {
+ int y1 = m_year;
+ int y2 = d.m_year;
+ int y = (m_signed) ? y2 - y1 : y1 - y2;
+
+ int m1 = m_month;
+ int m2 = d.m_month;
+ int months = (m_signed) ? m2 - m1 + (y*12) : m1 - m2 + (y*12);
+ sign = months > 0 ? "" : "-";
+
+ months = Math.abs(months);
+ monthDu = months%12;
+ yearDu = months/12;
+
+ }
+
+ return new Duration(sign + "P" + (yearDu != 0 ? (Integer.toString(yearDu) + "Y") : "") + (monthDu != 0 ? (Integer.toString(monthDu) + "M") : ""));
+
+ }
+
+ public Duration subtractYMDuration(Duration d)
+ throws TransformerException
+ {
+
+ String sign;
+ int monthDu, yearDu;
+
+ if (m_signed == d.m_signed)
+ {
+ int y1 = m_year;
+ int y2 = d.m_year;
+ int y = (m_signed) ? y2 - y1 : y1 - y2;
+
+ int m1 = m_month;
+ int m2 = d.m_month;
+ int months = (m_signed) ? m2 - m1 + (y*12) : m1 - m2 + (y*12);
+ sign = months > 0 ? "" : m_sign;
+
+ months = Math.abs(months);
+ monthDu = months%12;
+ yearDu = months/12;
+
+ }
+ else
+ {
+ sign = (m_signed) ? m_sign : "";
+ int months = m_month + d.m_month;
+ monthDu = months%12;
+ yearDu = months/12 + m_year + d.m_year;
+ }
+
+ return new Duration(sign + "P" + (yearDu != 0 ? (Integer.toString(yearDu) + "Y") : "") + (monthDu != 0 ? (Integer.toString(monthDu) + "M") : ""));
+
+ }
+
+ public Duration multiplyYMDuration(double dec)
+ throws TransformerException
+ {
+ int sign = (m_signed) ? -1 : 1;
+ double months = (m_month + (m_year * 12)) * dec * sign;
+ months = Math.floor(months + .5);
+
+ //months = (new Double(Math.floor(new Integer(months).doubleValue()))).intValue()
+
+ double ms = Math.abs(months);
+ int monthDu = (new Double(ms%12)).intValue();
+ int yearDu = (new Double(ms/12)).intValue();
+ //new Double(Math.floor(new Integer(months/12).doubleValue())).intValue();
+
+ return new Duration((months > 0 ? "" : m_sign) + "P" + (yearDu != 0 ? (Integer.toString(yearDu) + "Y") : "") + (monthDu != 0 ? (Integer.toString(monthDu) + "M") : ""));
+
+ }
+
+ public Duration divideYMDuration(double dec)
+ throws TransformerException
+ {int sign = (m_signed) ? -1 : 1;
+ double months = (m_month + (m_year * 12)) / dec * sign;
+ months = Math.floor(months + .5);
+
+ double ms = Math.abs(months);
+ int monthDu = (new Double(ms%12)).intValue();
+ int yearDu = (new Double(ms/12)).intValue();
+ //new Double(Math.floor(new Integer(months/12).doubleValue())).intValue();
+
+ return new Duration((months > 0 ? "" : m_sign) + "P" + (yearDu != 0 ? (Integer.toString(yearDu) + "Y") : "") + (monthDu != 0 ? (Integer.toString(monthDu) + "M") : ""));
+ }
+
+ public Duration addDTDuration(Duration du)
+ throws TransformerException
+ {
+ String sign;
+ int dayDu, hourDu, mnDu;
+ double secDu;
+ if (m_signed == du.m_signed) //!signed1 && !signed1 || signed1 && signed2)
+ {
+ sign = (m_signed) ? m_sign : "";
+ double secs = m_second + du.m_second;
+ secDu = secs%60;
+ int mins = (new Double(secs)).intValue()/60 + m_minute + du.m_minute;
+ mnDu = mins%60;
+ int hours = mins/60 + m_hour + du.m_hour;
+ hourDu = hours%24;
+ dayDu = hours/24 + m_day + du.m_day;
+ }
+ else
+ {
+ int d1 = m_day;
+ int d2 = du.m_day;
+ int d = (m_signed) ? d2 - d1 : d1 - d2;
+
+ int h1 = m_hour;
+ int h2 = du.m_hour;
+ int h = (m_signed) ? h2 - h1 + (d*24) : h1 - h2 + (d*24);
+
+ int m1 = m_minute;
+ int m2 = du.m_minute;
+ int m = (m_signed) ? m2 - m1 + (h*60) : m1 - m2 + (h*60);
+
+ double s1 = m_second;
+ double s2 = du.m_second;
+ double s = (m_signed) ? s2 - s1 + (m*60) : s1 - s2 + (m*60);
+ sign = s > 0 ? "" : m_sign;
+
+ s = Math.abs(s);
+ secDu = s%60;
+ m = (new Double(s)).intValue()/60;
+ mnDu = m%60;
+ h = m/60;
+ hourDu = h%24;
+ dayDu = h/24;
+
+ }
+
+ return new Duration(sign + "P" + (dayDu != 0 ? (Integer.toString(dayDu) + "D") : "")
+ + ((hourDu != 0 || mnDu != 0 || secDu != 0) ? "T" : "")
+ + (hourDu != 0 ? (Integer.toString(hourDu) + "H") : "")
+ + (mnDu != 0 ? (Integer.toString(mnDu) + "M") : "")
+ + (secDu != 0 ? (Double.toString(secDu) + "S") : "") );
+ }
+
+ public Duration subtractDTDuration(Duration du)
+ throws TransformerException
+ {
+ String sign;
+ int dayDu, hourDu, mnDu;
+ double secDu;
+ if (m_signed == du.m_signed)
+ {
+ int d1 = m_day;
+ int d2 = du.m_day;
+ int d = (m_signed) ? d2 - d1 : d1 - d2;
+
+ int h1 = m_hour;
+ int h2 = du.m_hour;
+ int h = (m_signed) ? h2 - h1 + (d*24) : h1 - h2 + (d*24);
+
+ int m1 = m_minute;
+ int m2 = du.m_minute;
+ int m = (m_signed) ? m2 - m1 + (h*60) : m1 - m2 + (h*60);
+
+ double s1 = m_second;
+ double s2 = du.m_second;
+ double s = (m_signed) ? s2 - s1 + (m*60) : s1 - s2 + (m*60);
+ sign = s > 0 ? "" : m_sign;
+
+ s = Math.abs(s);
+ secDu = s%60;
+ m = (new Double(s)).intValue()/60;
+ mnDu = m%60;
+ h = m/60;
+ hourDu = h%24;
+ dayDu = h/24;
+
+ }
+ else
+ {
+ sign = (m_signed) ? m_sign : "";
+ double secs = m_second + du.m_second;
+ secDu = secs%60;
+ int mins = (new Double(secs)).intValue()/60 + m_minute + du.m_minute;
+ mnDu = mins%60;
+ int hours = mins/60 + m_hour + du.m_hour;
+ hourDu = hours%24;
+ dayDu = hours/24 + m_day + du.m_day;
+ }
+
+
+ return new Duration(sign + "P" + (dayDu != 0 ? (Integer.toString(dayDu) + "D") : "")
+ + ((hourDu != 0 || mnDu != 0 || secDu != 0) ? "T" : "")
+ + (hourDu != 0 ? (Integer.toString(hourDu) + "H") : "")
+ + (mnDu != 0 ? (Integer.toString(mnDu) + "M") : "")
+ + (secDu != 0 ? (Double.toString(secDu) + "S") : "") );
+ }
+
+ public Duration multiplyDTDuration(double dec)
+ throws TransformerException
+ {
+ int sign = (m_signed) ? -1 : 1;
+ int hrs = m_hour + (m_day * 24);
+ int mns = m_minute + (hrs * 60);
+ double secs = (m_second + (mns * 60)) * dec * sign;
+
+ double s = Math.abs(secs);
+ double secDu = s%60;
+ mns = (new Double(s/60)).intValue();
+ int mnDu = mns%60;
+ hrs = mns/60;
+ int hrDu = hrs%24;
+ int dayDu = hrs/24;
+
+ return new Duration((secs > 0 ? "" : m_sign) + "P" + (dayDu != 0 ? (Integer.toString(dayDu) + "D") : "")
+ + ((hrDu != 0 || mnDu != 0 || secDu != 0) ? "T" : "")
+ + (hrDu != 0 ? (Integer.toString(hrDu) + "H") : "")
+ + (mnDu != 0 ? (Integer.toString(mnDu) + "M") : "")
+ + (secDu != 0 ? (Double.toString(secDu) + "S") : ""));
+
+ }
+
+ public Duration divideDTDuration(double dec)
+ throws TransformerException
+ {
+ int sign = (m_signed) ? -1 : 1;
+ int hrs = m_hour + (m_day * 24);
+ int mns = m_minute + (hrs * 60);
+ double secs = Math.floor(((m_second + (mns * 60)) / dec) + .5) * sign;
+ secs = Math.floor(secs);
+
+ double s = Math.abs(secs);
+ double secDu = s%60;
+ mns = (new Double(s/60)).intValue();
+ int mnDu = mns%60;
+ hrs = mns/60;
+ int hrDu = hrs%24;
+ int dayDu = hrs/24;
+ return new Duration((secs > 0 ? "" : m_sign) + "P" + (dayDu != 0 ? (Integer.toString(dayDu) + "D") : "")
+ + ((hrDu != 0 || mnDu != 0 || secDu != 0) ? "T" : "")
+ + (hrDu != 0 ? (Integer.toString(hrDu) + "H") : "")
+ + (mnDu != 0 ? (Integer.toString(mnDu) + "M") : "")
+ + (secDu != 0 ? (Double.toString(secDu) + "S") : ""));
+ }
+
+ public void setYears(int years)
+ {
+ m_year = years;
+ }
+
+ public int getYears()
+ {
+ return m_year;
+ }
+
+ public void setMonths(int months)
+ {
+ m_month = months;
+ }
+
+ public int getMonths()
+ {
+ return m_month;
+ }
+
+ public void setDays(int days)
+ {
+ m_day = days;
+ }
+
+ public int getDays()
+ {
+ return m_day;
+ }
+
+ public void setHours(int hours)
+ {
+ m_hour = hours;
+ }
+
+ public int getHours()
+ {
+ return m_hour;
+ }
+
+ public void setSeconds(double secs)
+ {
+ m_second = secs;
+ }
+
+ public double getSeconds()
+ {
+ return m_second;
+ }
+
+ public void setMinutes(int mts)
+ {
+ m_minute = mts;
+ }
+
+ public int getMinutes()
+ {
+ return m_minute;
+ }
+
+ public boolean getSigned()
+ {
+ return m_signed;
+ }
+
+ public String toString()
+ {
+ if (null == m_duration)
+ {
+ m_duration =
+ (m_signed ? m_sign : "")
+ + "P"
+ + ((m_year > 0) ? m_year + "Y" : "")
+ + ((m_month > 0) ? m_month + "M" : "")
+ + ((m_day > 0) ? m_day +"D": "")
+ + ((m_hour != 0 || m_minute != 0 || m_second != 0) ? "T" : "")
+ + ((m_hour != 0) ? m_hour + "H" : "")
+ + ((m_minute != 0) ? m_minute + "M" : "")
+ + ((m_second != 0) ? m_second + "S" : "");
+ }
+
+ return m_duration;
+ // return m_duration;
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/src/org/apache/xml/utils/FastStringBuffer.java b/src/org/apache/xml/utils/FastStringBuffer.java
index 05a8d9f..71c0c98 100644
--- a/src/org/apache/xml/utils/FastStringBuffer.java
+++ b/src/org/apache/xml/utils/FastStringBuffer.java
@@ -1373,4 +1373,162 @@
source.m_chunkSize = 1 << (source.m_chunkBits);
source.m_chunkMask = source.m_chunkSize - 1;
}
+
+ /** Support for DTM2XNI. Rather than push XNI awareness into this class,
+ * (as we did for SAX in sendSAX*), yield the content in a reasonably
+ * efficient manner for the caller to pass along.
+ * */
+ public CharacterBlockEnumeration enumerateCharacterBlocks(int start, int length)
+ {
+ return new FSBCharacterBlockEnumeration(start,length);
+ }
+
+ /** Support for DTM2XNI. Rather than push XNI awareness into this class,
+ * (as we did for SAX in sendSAX*), yield the content in a reasonably
+ * efficient manner for the caller to pass along.
+ *
+ * %BUG% %REVIEW% Currently does _NOT_ support inner FSBs.
+ * We need to either rearchitect those or get rid of 'em...
+ * */
+ protected class FSBCharacterBlockEnumeration
+ extends CharacterBlockEnumeration
+ {
+ int f_remaining;
+ int f_chunk;
+
+ FSBCharacterBlockEnumeration(int start,int length)
+ {
+ if(m_innerFSB!=null)
+ throw new UnsupportedOperationException("Can't handle innerFSBs yet");
+
+ int l=length();
+ if(start>l)
+ {
+ // Don't start off end -- take that as empty
+ _start=_length=f_remaining=0;
+ _chars=m_array[0];
+ }
+ else
+ {
+ // Don't run off end -- truncate to fit
+ l-=start;
+ f_remaining = (l>length) ? length : l;
+
+ // Set up first chunk
+ f_chunk=start>>>m_chunkBits;
+
+ _start=start & m_chunkMask;
+
+ l=m_chunkSize-start;
+ _length = (l>f_remaining) ? f_remaining : l;
+
+ f_remaining -= _length;
+ }
+ }
+
+ /** Not supported in this implementaton */
+ public FSBCharacterBlockEnumeration()
+ {
+ throw new UnsupportedOperationException("Not supported in this implementaton");
+ }
+
+ /** Not supported in this implementaton */
+ public FSBCharacterBlockEnumeration(String s)
+ {
+ throw new UnsupportedOperationException("Not supported in this implementaton");
+ }
+
+ /** Not supported in this implementaton */
+ public FSBCharacterBlockEnumeration(String s, int start, int length)
+ {
+ throw new UnsupportedOperationException("Not supported in this implementaton");
+ }
+
+ /** Not supported in this implementaton */
+ public FSBCharacterBlockEnumeration(char[] ch)
+ {
+ throw new UnsupportedOperationException("Not supported in this implementaton");
+ }
+
+ /** Not supported in this implementaton */
+ public FSBCharacterBlockEnumeration(char[] ch, int start, int length)
+ {
+ throw new UnsupportedOperationException("Not supported in this implementaton");
+ }
+
+ /** @return true if another character block can be accessed by calling
+ * nextElement()
+ */
+ public boolean hasMoreElements()
+ {
+ return f_remaining>0;
+ }
+
+ /** Advance to the next character block.
+ *
+ * @returns either this CharacterBlockEnumeration object (as a
+ * transient accessor to the "element") or null if no more elements are available.
+ * This is a bit of a kluge, but it allows us to claim that we
+ * implement the Java Enumeration interface if we want to do so, and
+ * it seems to be as good or bad as any other return value.
+ * */
+ public Object nextElement()
+ {
+ if(f_remaining==0)
+ return null;
+
+ // Next chunk
+ ++f_chunk;
+ _start=0;
+ _length = (m_chunkSize>f_remaining) ? f_remaining : m_chunkSize;
+ f_remaining -= _length;
+ return this;
+ }
+
+
+ /** @return the starting offset in the current block's character array
+ * */
+ public int getStart()
+ {
+ return _start;
+ }
+
+ /** @return the length of the the current block
+ * */
+ public int getLength()
+ {
+ return _length;
+ }
+
+ /**
+ * @return the current block's character array. Data will begin at
+ * offset {start}.
+ * */
+ public char[] getChars()
+ {
+ char[] ch=(_length>0)
+ ? m_array[f_chunk]
+ : EMPTY;
+ return ch;
+ }
+
+ /** @param target A char[] to be copied into. If a buffer is not supplied
+ * we will create one.
+ *
+ * @param targetStart Offset in the target at which copying should begin.
+ *
+ * @return the buffer, filled with {length} characters starting at offset
+ * {targetStart}. Characters before or after that block should be unaffected.
+ * */
+ public char[] getChars(char[] target, int targetStart)
+ {
+ if(_length>0)
+ {
+ System.arraycopy(m_array[f_chunk],_start,target,targetStart,_length);
+ }
+
+ return target;
+ }
+
+ }
}
diff --git a/src/org/apache/xml/utils/ListingErrorHandler.java b/src/org/apache/xml/utils/ListingErrorHandler.java
index 5b977f7..750eb3c 100644
--- a/src/org/apache/xml/utils/ListingErrorHandler.java
+++ b/src/org/apache/xml/utils/ListingErrorHandler.java
@@ -57,22 +57,19 @@
package org.apache.xml.utils;
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import org.xml.sax.*;
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.SourceLocator;
import java.io.PrintWriter;
-import java.net.MalformedURLException;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
-
-import javax.xml.transform.ErrorListener;
-import javax.xml.transform.SourceLocator;
-import javax.xml.transform.TransformerException;
-import org.apache.xalan.res.XSLMessages;
-import org.apache.xalan.res.XSLTErrorResources;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
+import java.io.InputStream;
+import org.apache.xml.utils.SystemIDResolver;
/**
@@ -97,8 +94,7 @@
public ListingErrorHandler(PrintWriter pw)
{
if (null == pw)
- throw new NullPointerException(XSLMessages.createMessage(XSLTErrorResources.ER_ERRORHANDLER_CREATED_WITH_NULL_PRINTWRITER, null));
- // "ListingErrorHandler created with null PrintWriter!");
+ throw new NullPointerException("ListingErrorHandler created with null PrintWriter!");
m_pw = pw;
}
diff --git a/src/org/apache/xml/utils/QName.java b/src/org/apache/xml/utils/QName.java
index aeee751..ed6c353 100644
--- a/src/org/apache/xml/utils/QName.java
+++ b/src/org/apache/xml/utils/QName.java
@@ -125,41 +125,16 @@
*/
public QName(String namespaceURI, String localName)
{
- this(namespaceURI, localName, false);
- }
- /**
- * Constructs a new QName with the specified namespace URI and
- * local name.
- *
- * @param namespaceURI The namespace URI if known, or null
- * @param localName The local name
- * @param validate If true the new QName will be validated and an IllegalArgumentException will
- * be thrown if it is invalid.
- */
- public QName(String namespaceURI, String localName, boolean validate)
- {
-
- // This check was already here. So, for now, I will not add it to the validation
- // that is done when the validate parameter is true.
if (localName == null)
throw new IllegalArgumentException(XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_ARG_LOCALNAME_NULL, null)); //"Argument 'localName' is null");
- if (validate)
- {
- if (!XMLChar.isValidNCName(localName))
- {
- throw new IllegalArgumentException(XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
- }
- }
-
_namespaceURI = namespaceURI;
_localName = localName;
- m_hashCode = toString().hashCode();
+ m_hashCode = calcHashCode();
}
-
+
/**
* Constructs a new QName with the specified namespace URI, prefix
* and local name.
@@ -167,94 +142,37 @@
* @param namespaceURI The namespace URI if known, or null
* @param prefix The namespace prefix is known, or null
* @param localName The local name
- *
*/
public QName(String namespaceURI, String prefix, String localName)
{
- this(namespaceURI, prefix, localName, false);
- }
-
- /**
- * Constructs a new QName with the specified namespace URI, prefix
- * and local name.
- *
- * @param namespaceURI The namespace URI if known, or null
- * @param prefix The namespace prefix is known, or null
- * @param localName The local name
- * @param validate If true the new QName will be validated and an IllegalArgumentException will
- * be thrown if it is invalid.
- */
- public QName(String namespaceURI, String prefix, String localName, boolean validate)
- {
- // This check was already here. So, for now, I will not add it to the validation
- // that is done when the validate parameter is true.
if (localName == null)
throw new IllegalArgumentException(XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_ARG_LOCALNAME_NULL, null)); //"Argument 'localName' is null");
- if (validate)
- {
- if (!XMLChar.isValidNCName(localName))
- {
- throw new IllegalArgumentException(XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
- }
-
- if ((null != prefix) && (!XMLChar.isValidNCName(prefix)))
- {
- throw new IllegalArgumentException(XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_PREFIX_INVALID,null )); //"Argument 'prefix' not a valid NCName");
- }
-
- }
_namespaceURI = namespaceURI;
_prefix = prefix;
_localName = localName;
- m_hashCode = toString().hashCode();
- }
+ m_hashCode = calcHashCode();
+ }
/**
* Construct a QName from a string, without namespace resolution. Good
* for a few odd cases.
*
* @param localName Local part of qualified name
- *
*/
public QName(String localName)
{
- this(localName, false);
- }
-
- /**
- * Construct a QName from a string, without namespace resolution. Good
- * for a few odd cases.
- *
- * @param localName Local part of qualified name
- * @param validate If true the new QName will be validated and an IllegalArgumentException will
- * be thrown if it is invalid.
- */
- public QName(String localName, boolean validate)
- {
- // This check was already here. So, for now, I will not add it to the validation
- // that is done when the validate parameter is true.
if (localName == null)
throw new IllegalArgumentException(XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_ARG_LOCALNAME_NULL, null)); //"Argument 'localName' is null");
- if (validate)
- {
- if (!XMLChar.isValidNCName(localName))
- {
- throw new IllegalArgumentException(XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
- }
- }
_namespaceURI = null;
_localName = localName;
- m_hashCode = toString().hashCode();
- }
+ m_hashCode = calcHashCode();
+ }
/**
* Construct a QName from a string, resolving the prefix
@@ -266,21 +184,6 @@
*/
public QName(String qname, Stack namespaces)
{
- this(qname, namespaces, false);
- }
-
- /**
- * Construct a QName from a string, resolving the prefix
- * using the given namespace stack. The default namespace is
- * not resolved.
- *
- * @param qname Qualified name to resolve
- * @param namespaces Namespace stack to use to resolve namespace
- * @param validate If true the new QName will be validated and an IllegalArgumentException will
- * be thrown if it is invalid.
- */
- public QName(String qname, Stack namespaces, boolean validate)
- {
String namespace = null;
String prefix = null;
@@ -294,7 +197,6 @@
{
namespace = S_XMLNAMESPACEURI;
}
- // Do we want this?
else if (prefix.equals("xmlns"))
{
return;
@@ -333,18 +235,9 @@
_localName = (indexOfNSSep < 0)
? qname : qname.substring(indexOfNSSep + 1);
-
- if (validate)
- {
- if ((_localName == null) || (!XMLChar.isValidNCName(_localName)))
- {
- throw new IllegalArgumentException(XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
- }
- }
_namespaceURI = namespace;
_prefix = prefix;
- m_hashCode = toString().hashCode();
+ m_hashCode = calcHashCode();
}
/**
@@ -359,23 +252,6 @@
public QName(String qname, Element namespaceContext,
PrefixResolver resolver)
{
- this(qname, namespaceContext, resolver, false);
- }
-
- /**
- * Construct a QName from a string, resolving the prefix
- * using the given namespace context and prefix resolver.
- * The default namespace is not resolved.
- *
- * @param qname Qualified name to resolve
- * @param namespaceContext Namespace Context to use
- * @param resolver Prefix resolver for this context
- * @param validate If true the new QName will be validated and an IllegalArgumentException will
- * be thrown if it is invalid.
- */
- public QName(String qname, Element namespaceContext,
- PrefixResolver resolver, boolean validate)
- {
_namespaceURI = null;
@@ -393,12 +269,6 @@
{
_namespaceURI = S_XMLNAMESPACEURI;
}
-
- // Do we want this?
- else if (prefix.equals("xmlns"))
- {
- return;
- }
else
{
_namespaceURI = resolver.getNamespaceForPrefix(prefix,
@@ -422,20 +292,9 @@
_localName = (indexOfNSSep < 0)
? qname : qname.substring(indexOfNSSep + 1);
-
- if (validate)
- {
- if ((_localName == null) || (!XMLChar.isValidNCName(_localName)))
- {
- throw new IllegalArgumentException(XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
- }
- }
-
- m_hashCode = toString().hashCode();
+ m_hashCode = calcHashCode();
}
-
/**
* Construct a QName from a string, resolving the prefix
* using the given namespace stack. The default namespace is
@@ -446,38 +305,26 @@
*/
public QName(String qname, PrefixResolver resolver)
{
- this(qname, resolver, false);
- }
- /**
- * Construct a QName from a string, resolving the prefix
- * using the given namespace stack. The default namespace is
- * not resolved.
- *
- * @param qname Qualified name to resolve
- * @param resolver Prefix resolver for this context
- * @param validate If true the new QName will be validated and an IllegalArgumentException will
- * be thrown if it is invalid.
- */
- public QName(String qname, PrefixResolver resolver, boolean validate)
- {
-
- String prefix = null;
_namespaceURI = null;
int indexOfNSSep = qname.indexOf(':');
if (indexOfNSSep > 0)
{
- prefix = qname.substring(0, indexOfNSSep);
-
+ String prefix = qname.substring(0, indexOfNSSep);
+ _prefix = prefix;
+
if (prefix.equals("xml"))
{
_namespaceURI = S_XMLNAMESPACEURI;
}
else
{
- _namespaceURI = resolver.getNamespaceForPrefix(prefix);
+ if(null != resolver) // Bad idea, I know. -sb
+ _namespaceURI = resolver.getNamespaceForPrefix(prefix);
+ else
+ _namespaceURI = prefix;
}
if (null == _namespaceURI)
@@ -489,21 +336,9 @@
}
}
- _localName = (indexOfNSSep < 0)
- ? qname : qname.substring(indexOfNSSep + 1);
-
- if (validate)
- {
- if ((_localName == null) || (!XMLChar.isValidNCName(_localName)))
- {
- throw new IllegalArgumentException(XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
- }
- }
-
-
- m_hashCode = toString().hashCode();
- _prefix = prefix;
+ _localName = (indexOfNSSep < 0)
+ ? qname : qname.substring(indexOfNSSep + 1);
+ m_hashCode = calcHashCode();
}
/**
@@ -588,6 +423,15 @@
{
return getLocalName();
}
+
+ /**
+ * Calculate the hash code for this object.
+ * @return int The hashcode to be used.
+ */
+ int calcHashCode()
+ {
+ return _localName.hashCode();
+ }
/**
* Return the cached hashcode of the qualified name.
diff --git a/src/org/apache/xml/utils/SparseVector.java b/src/org/apache/xml/utils/SparseVector.java
new file mode 100644
index 0000000..d1fdfe3
--- /dev/null
+++ b/src/org/apache/xml/utils/SparseVector.java
@@ -0,0 +1,173 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999,2000 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xerces" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, International
+ * Business Machines, Inc., http://www.apache.org. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.xml.utils;
+
+// %REVIEW% Should this be based on SuballocatedIntVector instead?
+// (Unclear. Pools will rarely be huge. But if they ever are...)
+import org.apache.xml.utils.IntVector;
+import java.util.Vector;
+
+/** <p>SparseVector can be thought of as a replacement for
+ * Hashtable, using int-value hashcodes/keys directly rather than requiring
+ * that they be objectified as Integers.
+ * (A standard Hashtable is relatively
+ * inefficient at manipulating primitives as either keys or values.)</p>
+ *
+ * Note similarity to SparseVector, though that assigns its own keys
+ * (allowing it to use internal position as an implied additional column)
+ * and puts heavier emphasis on bidirectional mapping.
+ *
+ * <p>Design Priorities:
+ * <li>Index-to-Object lookup speed is critical.</li>
+ * <li>Object-to-index lookup speed is not.</li>
+ * <li>Threadsafety is not guaranteed at this level.
+ * Enforce that in the application if needed.</li>
+ * <li>Storage efficiency is a major issue; that's why we're using
+ * a sparse vector rather than a standard one.</li>
+ * <li>I'm assuming a relatively small number of values will be stored;
+ * the current primary use for this is xsi:type overrides in XNI2DTM,
+ * and it is hoped these will be infrequent. To make this more general
+ * it would need to be adaptive to size demands, as is Java's Hashtable.
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * Status: Not unit-tested.
+ * */
+public class SparseVector
+{
+ Vector m_values;
+ IntVector m_keys;
+ static final int HASHPRIME=101;
+ int[] m_hashStart=new int[HASHPRIME];
+ IntVector m_hashChain;
+ static final int NULL=-1;
+
+ public SparseVector()
+ {
+ m_values=new Vector();
+ m_keys=new IntVector();
+ m_hashChain=new IntVector(512);
+ removeAllElements();
+ }
+
+ public void removeAllElements()
+ {
+ m_values.removeAllElements();
+ m_keys.removeAllElements();
+ for(int i=0;i<HASHPRIME;++i)
+ m_hashStart[i]=NULL;
+ m_hashChain.removeAllElements();
+ }
+
+ /**
+ * @param value to be stored
+ * @param index to store it at
+ * @return previous value at that index (may be null), or null if none.
+ * */
+ public Object setElementAt(Object value,int index)
+ {
+ return maybeSetElementAt(value,index,true);
+ }
+
+ /**
+ * @param index to retrieve
+ * @return current value at that index (may be null), or null if none.
+ * */
+ public Object elementAt(int index)
+ {
+ return maybeSetElementAt(null,index,false);
+ }
+
+ protected Object maybeSetElementAt(Object value, int index,boolean set)
+ {
+ int hashslot=index%HASHPRIME;
+ if(hashslot<0) hashslot=-hashslot;
+
+ // Is it one we already know?
+ int hashlast=m_hashStart[hashslot];
+ int hashcandidate=hashlast;
+ while(hashcandidate!=NULL)
+ {
+ if(m_keys.elementAt(hashcandidate)==index)
+ {
+ // Found existing; update it
+ Object ret=m_values.elementAt(hashcandidate);
+ if(set)
+ m_values.setElementAt(value,hashcandidate);
+ return ret;
+ }
+ hashlast=hashcandidate;
+ hashcandidate=m_hashChain.elementAt(hashcandidate);
+ }
+
+ if(set)
+ {
+ // New value. Add to tables.
+ int newIndex=m_values.size();
+ m_values.addElement(value);
+ m_keys.addElement(index);
+ m_hashChain.addElement(NULL); // Initialize to no-following-same-hash
+ if(hashlast==NULL) // First for this hash
+ m_hashStart[hashslot]=newIndex;
+ else // Link from previous with same hash
+ m_hashChain.setElementAt(newIndex,hashlast);
+ }
+ return null;
+ }
+}
diff --git a/src/org/apache/xml/utils/StringToIntTable.java b/src/org/apache/xml/utils/StringToIntTable.java
index fdcc944..16888c1 100644
--- a/src/org/apache/xml/utils/StringToIntTable.java
+++ b/src/org/apache/xml/utils/StringToIntTable.java
@@ -64,8 +64,6 @@
public class StringToIntTable
{
- public static final int INVALID_KEY = -10000;
-
/** Block size to allocate */
private int m_blocksize;
@@ -157,8 +155,7 @@
*
* @param key String to look for
*
- * @return The String's int value
- *
+ * @return The String's int value or a bogus value if not found
*/
public final int get(String key)
{
@@ -169,7 +166,7 @@
return m_values[i];
}
- return INVALID_KEY;
+ return -10000; // Bogus value, needs to throw exception.
}
/**
@@ -177,13 +174,13 @@
*
* @param key String to look for
*
- * @return The string's int value
+ * @return The string's int value, or a bogus value if not found
*/
public final int getIgnoreCase(String key)
{
if (null == key)
- return INVALID_KEY;
+ return -10000; // Bogus value, needs to throw exception.
for (int i = 0; i < m_firstFree; i++)
{
@@ -191,7 +188,7 @@
return m_values[i];
}
- return INVALID_KEY;
+ return -10000; // Bogus value, needs to throw exception.
}
/**
@@ -212,21 +209,4 @@
return false;
}
-
- /**
- * Return array of keys in the table.
- *
- * @return Array of strings
- */
- public final String[] keys()
- {
- String [] keysArr = new String[m_firstFree];
-
- for (int i = 0; i < m_firstFree; i++)
- {
- keysArr[i] = m_map[i];
- }
-
- return keysArr;
- }
}
diff --git a/src/org/apache/xml/utils/SystemIDResolver.java b/src/org/apache/xml/utils/SystemIDResolver.java
index 7f2691c..9d295e5 100644
--- a/src/org/apache/xml/utils/SystemIDResolver.java
+++ b/src/org/apache/xml/utils/SystemIDResolver.java
@@ -263,8 +263,8 @@
// Not so sure if this is good. But, for now, I'll try it. We really must
// make sure the return from this function is a URL!
if((Character.isLetter(uriStr.charAt(0)) && (uriStr.charAt(1) == ':')
- && (uriStr.charAt(2) == '/') && (uriStr.length() == 3 || uriStr.charAt(3) != '/'))
- || ((uriStr.charAt(0) == '/') && (uriStr.length() == 1 || uriStr.charAt(1) != '/')))
+ && (uriStr.charAt(2) == '/') && (uriStr.charAt(3) != '/'))
+ || ((uriStr.charAt(0) == '/') && (uriStr.charAt(1) != '/')))
{
uriStr = "file:///"+uriStr;
}
diff --git a/src/org/apache/xml/utils/TreeWalker.java b/src/org/apache/xml/utils/TreeWalker.java
index 7eed85d..7457a6c 100644
--- a/src/org/apache/xml/utils/TreeWalker.java
+++ b/src/org/apache/xml/utils/TreeWalker.java
@@ -71,7 +71,6 @@
* This class does a pre-order walk of the DOM tree, calling a ContentHandler
* interface as it goes.
*/
-
public class TreeWalker
{
@@ -168,13 +167,8 @@
}
/**
- * Perform a pre-order traversal non-recursive style.
+ * Perform a pre-order traversal non-recursive style.
*
- * Note that TreeWalker assumes that the subtree is intended to represent
- * a complete (though not necessarily well-formed) document and, during a
- * traversal, startDocument and endDocument will always be issued to the
- * SAX listener.
- *
* @param pos Node in the tree where to start traversal
*
* @throws TransformerException
@@ -182,8 +176,6 @@
public void traverse(Node pos) throws org.xml.sax.SAXException
{
- this.m_contentHandler.startDocument();
-
Node top = pos;
while (null != pos)
@@ -219,16 +211,10 @@
pos = nextNode;
}
- this.m_contentHandler.endDocument();
}
/**
* Perform a pre-order traversal non-recursive style.
-
- * Note that TreeWalker assumes that the subtree is intended to represent
- * a complete (though not necessarily well-formed) document and, during a
- * traversal, startDocument and endDocument will always be issued to the
- * SAX listener.
*
* @param pos Node in the tree where to start traversal
* @param top Node in the tree where to end traversal
@@ -238,8 +224,6 @@
public void traverse(Node pos, Node top) throws org.xml.sax.SAXException
{
- this.m_contentHandler.startDocument();
-
while (null != pos)
{
startNode(pos);
@@ -270,7 +254,6 @@
pos = nextNode;
}
- this.m_contentHandler.endDocument();
}
/** Flag indicating whether following text to be processed is raw text */
@@ -342,7 +325,7 @@
// ??;
break;
case Node.DOCUMENT_NODE :
-
+ this.m_contentHandler.startDocument();
break;
case Node.ELEMENT_NODE :
NamedNodeMap atts = ((Element) node).getAttributes();
@@ -471,8 +454,8 @@
switch (node.getNodeType())
{
case Node.DOCUMENT_NODE :
+ this.m_contentHandler.endDocument();
break;
-
case Node.ELEMENT_NODE :
String ns = m_dh.getNamespaceOfNode(node);
if(null == ns)
diff --git a/src/org/apache/xml/utils/URI.java b/src/org/apache/xml/utils/URI.java
index e4ae1a2..30b142f 100644
--- a/src/org/apache/xml/utils/URI.java
+++ b/src/org/apache/xml/utils/URI.java
@@ -91,6 +91,7 @@
* default port for a specific scheme). Rather, it only knows the
* grammar and basic set of operations that can be applied to a URI.
*
+ * @version $Id$
*
*/
public class URI implements Serializable
diff --git a/src/org/apache/xml/utils/synthetic/JavaUtils.java b/src/org/apache/xml/utils/synthetic/JavaUtils.java
index a0a9267..b397454 100644
--- a/src/org/apache/xml/utils/synthetic/JavaUtils.java
+++ b/src/org/apache/xml/utils/synthetic/JavaUtils.java
@@ -54,6 +54,7 @@
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
+ * $Id$
*/
package org.apache.xml.utils.synthetic;