jkesselm 01/06/11 12:05:07
Modified: java/src/org/apache/xml/dtm/ref Tag: DTM_EXP
DTMDefaultBase.java
Log:
Namespace support changes; requires alterations to DOM2DTM and SAX2DTM
Revision Changes Path
No revision
No revision
1.1.2.7 +214 -164
xml-xalan/java/src/org/apache/xml/dtm/ref/Attic/DTMDefaultBase.java
Index: DTMDefaultBase.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xml/dtm/ref/Attic/DTMDefaultBase.java,v
retrieving revision 1.1.2.6
retrieving revision 1.1.2.7
diff -u -r1.1.2.6 -r1.1.2.7
--- DTMDefaultBase.java 2001/06/04 07:43:26 1.1.2.6
+++ DTMDefaultBase.java 2001/06/11 19:05:05 1.1.2.7
@@ -84,7 +84,6 @@
*/
public abstract class DTMDefaultBase implements DTM
{
-
/**
* The number of nodes, which is also used to determine the next
* node index.
@@ -110,7 +109,14 @@
protected int[] m_parent;
/** Experemental. -sb */
- protected boolean m_haveSeenNamespace = false;
+// protected boolean m_haveSeenNamespace = false;
+
+ /** Vector of IntVectors of NS decl sets -jjk */
+ protected Vector m_namespaceDeclSets = null;
+
+ /** IntVector of elements at which corresponding
+ * namespaceDeclSets were defined -jjk */
+ protected IntVector m_namespaceDeclSetElements = null;
/**
* These hold indexes to elements based on namespace and local name.
@@ -912,7 +918,6 @@
*/
public int getNextSibling(int nodeHandle)
{
-
return _nextsib(nodeHandle & m_mask) | m_dtmIdent;
}
@@ -968,107 +973,172 @@
return DTM.NULL;
}
- /** Lazily created namespace lists. */
- private Vector m_namespaceLists = null; // on demand
-
- /**
- * Get a full list of namespace handles for the given element. In other words
- * get all the namespace nodes in context for the given element.
- *
- *
- * @param baseHandle The base element handle.
- *
- * @return A list of namespace handles for this element.
- */
- protected NodeVector getNamespaceList(int baseHandle)
+ /** Build table of namespace declaration
+ * locations during DTM construction. Table is a Vector of
+ * IntVectors containing the namespace node HANDLES declared at
+ * that ID, plus an IntVector of the element node INDEXES at which
+ * these declarations appeared.
+ *
+ * NOTE: Since this occurs during model build, nodes will be encountered
+ * in doucment order and thus the table will be ordered by element,
+ * permitting binary-search as a possible retrieval optimization.
+ *
+ * %REVIEW% Directly managed arrays rather than vectors?
+ * %REVIEW% Handles or IDs? Given usage, I think handles.
+ * */
+ protected void declareNamespaceInContext(int elementNodeIndex,int
namespaceNodeIndex)
{
+ IntVector nsList=null;
+ if(m_namespaceDeclSets==null)
+ {
- if (null == m_namespaceLists)
- m_namespaceLists = new Vector();
+ // First
+ m_namespaceDeclSetElements=new IntVector();
+ m_namespaceDeclSetElements.addElement(elementNodeIndex);
+ m_namespaceDeclSets=new Vector();
+ nsList=new IntVector();
+ m_namespaceDeclSets.addElement(nsList);
+ }
else
- {
- int n = m_namespaceLists.size();
-
- for (int i = (n - 1); i >= 0; i--)
{
- NodeVector ivec = (NodeVector) m_namespaceLists.elementAt(i);
+ // Most recent?
+ // %OPT% Is there a lastElement() method? Should there be?
+ int last=m_namespaceDeclSetElements.size()-1;
- if (ivec.elementAt(0) == baseHandle)
- return ivec;
+ if(elementNodeIndex==
+ m_namespaceDeclSetElements.elementAt(last))
+ {
+ nsList=(IntVector)m_namespaceDeclSets.elementAt(last);
+
+ }
}
- }
+ if(nsList==null)
+ {
+ m_namespaceDeclSetElements.addElement(elementNodeIndex);
+ nsList=new IntVector();
+ m_namespaceDeclSets.addElement(nsList);
+
+ IntVector inherited= findNamespaceContext(_parent(elementNodeIndex));
- NodeVector ivec = buildNamespaceList(baseHandle);
+ if(inherited!=null)
+ {
+ // %OPT% Count-down might be faster, but debuggability may
+ // be better this way, and if we ever decide we want to
+ // keep this ordered by expanded-type...
+ int isize=inherited.size();
+ for(int i=0;i<isize;++i)
+ {
+ nsList.addElement(inherited.elementAt(i));
+ }
+ }
+ }
- m_namespaceLists.addElement(ivec);
+ // Handle overwriting inherited.
+ // %OPT% Keep sorted? (By expanded-name rather than by doc order...)
+ // Downside: Would require insertElementAt if not found,
+ // which has recopying costs. But these are generally short lists...
+ int newEType=getExpandedTypeID(namespaceNodeIndex);
- return ivec;
+ for(int i=nsList.size()-1;i>=0;--i)
+ {
+ if(newEType==getExpandedTypeID(nsList.elementAt(i)))
+ {
+ nsList.setElementAt(namespaceNodeIndex,i);
+ return;
+ }
+ }
+ nsList.addElement(namespaceNodeIndex | m_dtmIdent);
}
-
- /**
- * Build a list of all namespace nodes in context for this element.
- *
- *
- * @param baseHandle The base element handle.
- *
- * @return a NodeVector that contains a list of all namespace nodes in
- * context for this element.
- */
- private NodeVector buildNamespaceList(int baseHandle)
+
+ /** Retrieve list of namespace declaration locations
+ * active at this node. List is an IntVector whose
+ * entries are the namespace node HANDLES declared at that ID.
+ *
+ * %REVIEW% Directly managed arrays rather than vectors?
+ * %REVIEW% Handles or IDs? Given usage, I think handles.
+ * */
+ protected IntVector findNamespaceContext(int elementNodeIndex)
{
-
- NodeVector ivec = new NodeVector(7);
-
- ivec.addElement(-1); // for base handle.
-
- int nodeHandle = baseHandle;
- int type = getNodeType(baseHandle);
- int namespaceHandle = DTM.NULL;
-
- if (DTM.ELEMENT_NODE == type)
- {
-
- // We have to return in document order, so we actually want to find the
- // first namespace decl of the last element that has a namespace decl.
- // Assume that attributes and namespaces immediately follow the element.
- int identity = nodeHandle & m_mask;
-
- while (DTM.NULL != identity)
+ if (null!=m_namespaceDeclSetElements)
{
- identity = getNextNodeIdentity(identity);
- type = (DTM.NULL == identity) ? -1 : getNodeType(identity);
-
- if (type == DTM.NAMESPACE_NODE)
- {
- namespaceHandle = identity | m_dtmIdent;
-
- ivec.insertInOrder(namespaceHandle);
- }
- else if (DTM.ATTRIBUTE_NODE != type)
- {
- if (identity > 0)
+ // %OPT% Is binary-search really saving us a lot versus linear?
+ // (... It may be, in large docs with many NS decls.)
+ int wouldBeAt=findInSortedIntVector(m_namespaceDeclSetElements,
+ elementNodeIndex);
+ if(wouldBeAt>=0) // Found it
+ return (IntVector) m_namespaceDeclSets.elementAt(wouldBeAt);
+ if(wouldBeAt == -1) // -1-wouldbeat == 0
+ return null; // Not after anything; definitely not found
+
+ // Not found, but we know where it should have been.
+ // Search back until we find an ancestor or run out.
+ wouldBeAt=-1-wouldBeAt;
+
+ // Decrement wouldBeAt to find last possible ancestor
+ int candidate=m_namespaceDeclSetElements.elementAt(-- wouldBeAt);
+ int ancestor=_parent(elementNodeIndex);
+ while(wouldBeAt>=0 && ancestor>0)
{
- nodeHandle = getParent(nodeHandle);
+ candidate=m_namespaceDeclSetElements.elementAt(wouldBeAt);
- if (nodeHandle == DTM.NULL)
- break;
+ if(candidate==ancestor) // Found ancestor in list
+ return (IntVector)m_namespaceDeclSets.elementAt(wouldBeAt);
+ else if(candidate<ancestor) // Too deep in tree
+ ancestor=_parent(ancestor);
+ else // Too late in list
+ --wouldBeAt;
+ }
+ }
- identity = nodeHandle & m_mask;
+ return null; // No namespaces known at this node
+ }
- if (identity == 0)
- break;
- }
- else
- break;
+ /**
+ * Subroutine: Locate the specified node within
+ * m_namespaceDeclSetElements, or the last element which
+ * preceeds it in document order
+ *
+ * %REVIEW% Inlne this into findNamespaceContext? Create SortedIntVector type?
+ *
+ * @param elementNodeIndex Index of a node to look up.
+ *
+ * @return If positive or zero, the index of the found item.
+ * If negative, index of the point at which it would have appeared,
+ * encoded as -1-index and hence reconvertable by subtracting
+ * it from -1. (Encoding because I don't want to recompare the strings
+ * but don't want to burn bytes on a datatype to hold a flagged value.)
+ */
+ protected int findInSortedIntVector(IntVector vector, int lookfor)
+ {
+ // Binary search
+ int i = 0;
+ if(vector != null) {
+ int first = 0;
+ int last = vector.size() - 1;
+
+ while (first <= last) {
+ i = (first + last) / 2;
+ int test = lookfor-vector.elementAt(i);
+ if(test == 0) {
+ return i; // Name found
+ }
+ else if (test < 0) {
+ last = i - 1; // looked too late
+ }
+ else {
+ first = i + 1; // looked ot early
}
}
+
+ if (first > i) {
+ i = first; // Clean up at loop end
+ }
}
-
- ivec.setElementAt(baseHandle, 0);
- return ivec;
+ return -1 - i; // not-found has to be encoded.
}
+
/**
* Given a node handle, get the index of the node's first child.
* If not yet resolved, waits for more nodes to be added to the document and
@@ -1084,46 +1154,33 @@
*/
public int getFirstNamespaceNode(int nodeHandle, boolean inScope)
{
- if(!m_haveSeenNamespace)
- return NULL;
-
- int type = getNodeType(nodeHandle);
-
- if (DTM.ELEMENT_NODE == type)
- {
- if (inScope)
- {
- NodeVector namespaces = getNamespaceList(nodeHandle);
- int n = namespaces.size();
-
- if (n > 1)
- return namespaces.elementAt(1);
- }
- else
- {
-
- // Assume that attributes and namespaces immediately follow the element.
- int identity = nodeHandle & m_mask;
-
- while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
- {
-
- // Assume this can not be null.
- type = getNodeType(identity);
-
- if (type == DTM.NAMESPACE_NODE)
- {
- return identity | m_dtmIdent;
- }
- else if (DTM.ATTRIBUTE_NODE != type)
- {
- break;
- }
- }
- }
- }
-
- return DTM.NULL;
+ if(inScope)
+ {
+ IntVector nsContext=findNamespaceContext(nodeHandle & m_mask);
+ if(nsContext==null || nsContext.size()<1)
+ return NULL;
+
+ return nsContext.elementAt(0);
+ }
+ else
+ {
+ // Assume that attributes and namespaces immediately
+ // follow the element.
+ //
+ // %OPT% Would things be faster if all NS nodes were built
+ // before all Attr nodes? Some costs at build time for 2nd
+ // pass...
+ int identity = nodeHandle & m_mask;
+ while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
+ {
+ int type = getNodeType(identity);
+ if (type == DTM.NAMESPACE_NODE)
+ return identity | m_dtmIdent;
+ else if (DTM.ATTRIBUTE_NODE != type)
+ break;
+ }
+ return NULL;
+ }
}
/**
@@ -1141,48 +1198,41 @@
public int getNextNamespaceNode(int baseHandle, int nodeHandle,
boolean inScope)
{
-
- int type = getNodeType(nodeHandle);
-
- if (DTM.NAMESPACE_NODE == type)
- {
- if (inScope)
- {
- NodeVector namespaces = getNamespaceList(baseHandle);
- int n = namespaces.size();
-
- for (int i = 1; i < n; i++) // start from 1 on purpose
- {
- if (nodeHandle == namespaces.elementAt(i))
- {
- if (i + 1 < n)
- return namespaces.elementAt(i + 1);
- }
- }
- }
- else
- {
-
- // Assume that attributes and namespace nodes immediately follow the
element.
- int identity = nodeHandle & m_mask;
-
- while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
- {
- type = getNodeType(identity);
-
- if (type == DTM.NAMESPACE_NODE)
- {
- return identity | m_dtmIdent;
- }
- else if (type != DTM.ATTRIBUTE_NODE)
- {
- break;
- }
- }
- }
- }
-
- return DTM.NULL;
+ if(inScope)
+ {
+ //Since we've been given the base, try direct lookup
+ //(could look from nodeHandle but this is at least one
+ //comparison/get-parent faster)
+ //IntVector nsContext=findNamespaceContext(nodeHandle & m_mask);
+
+ IntVector nsContext=findNamespaceContext(baseHandle & m_mask);
+
+ if(nsContext==null)
+ return NULL;
+ int i=1 + nsContext.indexOf(nodeHandle);
+ if(i<=0 || i==nsContext.size())
+ return NULL;
+
+ return nsContext.elementAt(i);
+ }
+ else
+ {
+ // Assume that attributes and namespace nodes immediately follow the
element.
+ int identity = nodeHandle & m_mask;
+ while (DTM.NULL != (identity = getNextNodeIdentity(identity)))
+ {
+ int type = getNodeType(identity);
+ if (type == DTM.NAMESPACE_NODE)
+ {
+ return identity | m_dtmIdent;
+ }
+ else if (type != DTM.ATTRIBUTE_NODE)
+ {
+ break;
+ }
+ }
+ }
+ return DTM.NULL;
}
/**
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]