| Method from com.sun.org.apache.xml.internal.dtm.ref.sax2dtm.SAX2DTM Detail: |
protected int _dataOrQName(int identity) {
if (identity < m_size)
return m_dataOrQName.elementAt(identity);
// Check to see if the information requested has been processed, and,
// if not, advance the iterator until we the information has been
// processed.
while (true)
{
boolean isMore = nextNode();
if (!isMore)
return NULL;
else if (identity < m_size)
return m_dataOrQName.elementAt(identity);
}
}
Get the data or qualified name for the given node identity. |
protected void addNewDTMID(int nodeIndex) {
try
{
if(m_mgr==null)
throw new ClassCastException();
// Handle as Extended Addressing
DTMManagerDefault mgrD=(DTMManagerDefault)m_mgr;
int id=mgrD.getFirstFreeDTMID();
mgrD.addDTM(this,id,nodeIndex);
m_dtmIdent.addElement(id< < DTMManager.IDENT_DTM_NODE_BITS);
}
catch(ClassCastException e)
{
// %REVIEW% Wrong error message, but I've been told we're trying
// not to add messages right not for I18N reasons.
// %REVIEW% Should this be a Fatal Error?
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_NO_DTMIDS_AVAIL, null));//"No more DTM IDs are available";
}
}
Get a new DTM ID beginning at the specified node index. |
protected int addNode(int type,
int expandedTypeID,
int parentIndex,
int previousSibling,
int dataOrPrefix,
boolean canHaveFirstChild) {
// Common to all nodes:
int nodeIndex = m_size++;
// Have we overflowed a DTM Identity's addressing range?
if(m_dtmIdent.size() == (nodeIndex > > >DTMManager.IDENT_DTM_NODE_BITS))
{
addNewDTMID(nodeIndex);
}
m_firstch.addElement(canHaveFirstChild ? NOTPROCESSED : DTM.NULL);
m_nextsib.addElement(NOTPROCESSED);
m_parent.addElement(parentIndex);
m_exptype.addElement(expandedTypeID);
m_dataOrQName.addElement(dataOrPrefix);
if (m_prevsib != null) {
m_prevsib.addElement(previousSibling);
}
if (DTM.NULL != previousSibling) {
m_nextsib.setElementAt(nodeIndex,previousSibling);
}
if (m_locator != null && m_useSourceLocationProperty) {
setSourceLocation();
}
// Note that nextSibling is not processed until charactersFlush()
// is called, to handle successive characters() events.
// Special handling by type: Declare namespaces, attach first child
switch(type)
{
case DTM.NAMESPACE_NODE:
declareNamespaceInContext(parentIndex,nodeIndex);
break;
case DTM.ATTRIBUTE_NODE:
break;
default:
if (DTM.NULL == previousSibling && DTM.NULL != parentIndex) {
m_firstch.setElementAt(nodeIndex,parentIndex);
}
break;
}
return nodeIndex;
}
Construct the node map from the node. |
public void attributeDecl(String eName,
String aName,
String type,
String valueDefault,
String value) throws SAXException {
// no op
}
Report an attribute type declaration.
Only the effective (first) declaration for an attribute will
be reported. The type will be one of the strings "CDATA",
"ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY",
"ENTITIES", or "NOTATION", or a parenthesized token group with
the separator "|" and all whitespace removed. |
public void characters(char[] ch,
int start,
int length) throws SAXException {
if (m_textPendingStart == -1) // First one in this block
{
m_textPendingStart = m_chars.size();
m_coalescedTextType = m_textType;
}
// Type logic: If all adjacent text is CDATASections, the
// concatentated text is treated as a single CDATASection (see
// initialization above). If any were ordinary Text, the whole
// thing is treated as Text. This may be worth %REVIEW%ing.
else if (m_textType == DTM.TEXT_NODE)
{
m_coalescedTextType = DTM.TEXT_NODE;
}
m_chars.append(ch, start, length);
}
Receive notification of character data inside an element.
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). |
protected void charactersFlush() {
if (m_textPendingStart >= 0) // -1 indicates no-text-in-progress
{
int length = m_chars.size() - m_textPendingStart;
boolean doStrip = false;
if (getShouldStripWhitespace())
{
doStrip = m_chars.isWhitespace(m_textPendingStart, length);
}
if (doStrip) {
m_chars.setLength(m_textPendingStart); // Discard accumulated text
} else {
// Guard against characters/ignorableWhitespace events that
// contained no characters. They should not result in a node.
if (length > 0) {
int exName = m_expandedNameTable.getExpandedTypeID(DTM.TEXT_NODE);
int dataIndex = m_data.size();
m_previous = addNode(m_coalescedTextType, exName,
m_parents.peek(), m_previous, dataIndex, false);
m_data.addElement(m_textPendingStart);
m_data.addElement(length);
}
}
// Reset for next text block
m_textPendingStart = -1;
m_textType = m_coalescedTextType = DTM.TEXT_NODE;
}
}
Check whether accumulated text should be stripped; if not,
append the appropriate flavor of text/cdata node. |
public void clearCoRoutine() {
clearCoRoutine(true);
}
Ask the CoRoutine parser to doTerminate and clear the reference. |
public void clearCoRoutine(boolean callDoTerminate) {
if (null != m_incrementalSAXSource)
{
if (callDoTerminate)
m_incrementalSAXSource.deliverMoreNodes(false);
m_incrementalSAXSource = null;
}
}
Ask the CoRoutine parser to doTerminate and clear the reference. If
the CoRoutine parser has already been cleared, this will have no effect. |
public void comment(char[] ch,
int start,
int length) throws SAXException {
if (m_insideDTD) // ignore comments if we're inside the DTD
return;
charactersFlush();
int exName = m_expandedNameTable.getExpandedTypeID(DTM.COMMENT_NODE);
// For now, treat comments as strings... I guess we should do a
// seperate FSB buffer instead.
int dataIndex = m_valuesOrPrefixes.stringToIndex(new String(ch, start,
length));
m_previous = addNode(DTM.COMMENT_NODE, exName,
m_parents.peek(), m_previous, dataIndex, false);
}
Report an XML comment anywhere in the document.
This callback will be used for comments inside or outside the
document element, including comments in the external DTD
subset (if read). |
protected boolean declAlreadyDeclared(String prefix) {
int startDecls = m_contextIndexes.peek();
java.util.Vector prefixMappings = m_prefixMappings;
int nDecls = prefixMappings.size();
for (int i = startDecls; i < nDecls; i += 2)
{
String prefixDecl = (String) prefixMappings.elementAt(i);
if (prefixDecl == null)
continue;
if (prefixDecl.equals(prefix))
return true;
}
return false;
}
Check if a declaration has already been made for a given prefix. |
public void dispatchCharactersEvents(int nodeHandle,
ContentHandler ch,
boolean normalize) throws SAXException {
int identity = makeNodeIdentity(nodeHandle);
if (identity == DTM.NULL)
return;
int type = _type(identity);
if (isTextType(type))
{
int dataIndex = m_dataOrQName.elementAt(identity);
int offset = m_data.elementAt(dataIndex);
int length = m_data.elementAt(dataIndex + 1);
if(normalize)
m_chars.sendNormalizedSAXcharacters(ch, offset, length);
else
m_chars.sendSAXcharacters(ch, offset, length);
}
else
{
int firstChild = _firstch(identity);
if (DTM.NULL != firstChild)
{
int offset = -1;
int length = 0;
int startNode = identity;
identity = firstChild;
do {
type = _type(identity);
if (isTextType(type))
{
int dataIndex = _dataOrQName(identity);
if (-1 == offset)
{
offset = m_data.elementAt(dataIndex);
}
length += m_data.elementAt(dataIndex + 1);
}
identity = getNextNodeIdentity(identity);
} while (DTM.NULL != identity && (_parent(identity) >= startNode));
if (length > 0)
{
if(normalize)
m_chars.sendNormalizedSAXcharacters(ch, offset, length);
else
m_chars.sendSAXcharacters(ch, offset, length);
}
}
else if(type != DTM.ELEMENT_NODE)
{
int dataIndex = _dataOrQName(identity);
if (dataIndex < 0)
{
dataIndex = -dataIndex;
dataIndex = m_data.elementAt(dataIndex + 1);
}
String str = m_valuesOrPrefixes.indexToString(dataIndex);
if(normalize)
FastStringBuffer.sendNormalizedSAXcharacters(str.toCharArray(),
0, str.length(), ch);
else
ch.characters(str.toCharArray(), 0, str.length());
}
}
}
Directly call the
characters method on the passed ContentHandler for the
string-value of the given node (see http://www.w3.org/TR/xpath#data-model
for the definition of a node's string-value). Multiple calls to the
ContentHandler's characters methods may well occur for a single call to
this method. |
public void dispatchToEvents(int nodeHandle,
ContentHandler ch) throws SAXException {
DTMTreeWalker treeWalker = m_walker;
ContentHandler prevCH = treeWalker.getcontentHandler();
if (null != prevCH)
{
treeWalker = new DTMTreeWalker();
}
treeWalker.setcontentHandler(ch);
treeWalker.setDTM(this);
try
{
treeWalker.traverse(nodeHandle);
}
finally
{
treeWalker.setcontentHandler(null);
}
}
Directly create SAX parser events from a subtree. |
public void elementDecl(String name,
String model) throws SAXException {
// no op
}
Report an element type declaration.
The content model will consist of the string "EMPTY", the
string "ANY", or a parenthesised group, optionally followed
by an occurrence indicator. The model will be normalized so
that all whitespace is removed,and will include the enclosing
parentheses. |
public void endCDATA() throws SAXException {
m_textType = DTM.TEXT_NODE;
}
Report the end of a CDATA section. |
public void endDTD() throws SAXException {
m_insideDTD = false;
}
Report the end of DTD declarations. |
public void endDocument() throws SAXException {
if (DEBUG)
System.out.println("endDocument");
charactersFlush();
m_nextsib.setElementAt(NULL,0);
if (m_firstch.elementAt(0) == NOTPROCESSED)
m_firstch.setElementAt(NULL,0);
if (DTM.NULL != m_previous)
m_nextsib.setElementAt(DTM.NULL,m_previous);
m_parents = null;
m_prefixMappings = null;
m_contextIndexes = null;
m_endDocumentOccured = true;
// Bugzilla 4858: throw away m_locator. we cache m_systemId
m_locator = null;
}
Receive notification of the end of the document. |
public void endElement(String uri,
String localName,
String qName) throws SAXException {
if (DEBUG)
System.out.println("endElement: uri: " + uri + ", localname: "
+ localName + ", qname: "+qName);
charactersFlush();
// If no one noticed, startPrefixMapping is a drag.
// Pop the context for the last child (the one pushed by startElement)
m_contextIndexes.quickPop(1);
// Do it again for this one (the one pushed by the last endElement).
int topContextIndex = m_contextIndexes.peek();
if (topContextIndex != m_prefixMappings.size()) {
m_prefixMappings.setSize(topContextIndex);
}
int lastNode = m_previous;
m_previous = m_parents.pop();
// If lastNode is still DTM.NULL, this element had no children
if (DTM.NULL == lastNode)
m_firstch.setElementAt(DTM.NULL,m_previous);
else
m_nextsib.setElementAt(DTM.NULL,lastNode);
popShouldStripWhitespace();
}
Receive notification of the end of an element.
By default, do nothing. Application writers may override this
method in a subclass to take specific actions at the end of
each element (such as finalising a tree node or writing
output to a file). |
public void endEntity(String name) throws SAXException {
// no op
}
Report the end of an entity. |
public void endPrefixMapping(String prefix) throws SAXException {
if (DEBUG)
System.out.println("endPrefixMapping: prefix: " + prefix);
if(null == prefix)
prefix = "";
int index = m_contextIndexes.peek() - 1;
do
{
index = m_prefixMappings.indexOf(prefix, ++index);
} while ( (index >= 0) && ((index & 0x01) == 0x01) );
if (index > -1)
{
m_prefixMappings.setElementAt("%@$#^@#", index);
m_prefixMappings.setElementAt("%@$#^@#", index + 1);
}
// no op
}
Receive notification of the end of a Namespace mapping.
By default, do nothing. Application writers may override this
method in a subclass to take specific actions at the end of
each prefix mapping. |
public void error(SAXParseException e) throws SAXException {
throw e;
}
Receive notification of a recoverable parser error.
The default implementation does nothing. Application writers
may override this method in a subclass to take specific actions
for each error, such as inserting the message in a log file or
printing it to the console. |
public void externalEntityDecl(String name,
String publicId,
String systemId) throws SAXException {
// no op
}
|
public void fatalError(SAXParseException e) throws SAXException {
throw e;
}
Report a fatal XML parsing error.
The default implementation throws a SAXParseException.
Application writers may override this method in a subclass if
they need to take specific actions for each fatal error (such as
collecting all of the errors into a single report): in any case,
the application must stop all regular processing when this
method is invoked, since the document is no longer reliable, and
the parser may no longer report parsing events. |
public int getAttributeNode(int nodeHandle,
String namespaceURI,
String name) {
for (int attrH = getFirstAttribute(nodeHandle); DTM.NULL != attrH;
attrH = getNextAttribute(attrH))
{
String attrNS = getNamespaceURI(attrH);
String attrName = getLocalName(attrH);
boolean nsMatch = namespaceURI == attrNS
|| (namespaceURI != null
&& namespaceURI.equals(attrNS));
if (nsMatch && name.equals(attrName))
return attrH;
}
return DTM.NULL;
}
Retrieves an attribute node by by qualified name and namespace URI. |
public ContentHandler getContentHandler() {
if (m_incrementalSAXSource.getClass()
.getName().equals("com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Filter"))
return (ContentHandler) m_incrementalSAXSource;
else
return this;
}
getContentHandler returns "our SAX builder" -- the thing that
someone else should send SAX events to in order to extend this
DTM model.
%REVIEW% Should this return null if constrution already done/begun? |
public DTDHandler getDTDHandler() {
return this;
}
Return this DTM's DTDHandler. |
public DeclHandler getDeclHandler() {
return this;
}
Return this DTM's DeclHandler. |
public String getDocumentTypeDeclarationPublicIdentifier() {
/** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMDefaultBase abstract method */
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"Not yet supported!");
return null;
}
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. |
public String getDocumentTypeDeclarationSystemIdentifier() {
/** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMDefaultBase abstract method */
error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"Not yet supported!");
return null;
}
A document type declaration information item has the following properties:
1. [system identifier] The system identifier of the external subset, if
it exists. Otherwise this property has no value. |
public int getElementById(String elementId) {
Integer intObj;
boolean isMore = true;
do
{
intObj = (Integer) m_idAttributes.get(elementId);
if (null != intObj)
return makeNodeHandle(intObj.intValue());
if (!isMore || m_endDocumentOccured)
break;
isMore = nextNode();
}
while (null == intObj);
return DTM.NULL;
}
Returns the Element whose ID is given by
elementId. If no such element exists, returns
DTM.NULL. Behavior is not defined if more than one element
has this ID. Attributes (including those
with the name "ID") are not of type ID unless so defined by DTD/Schema
information available to the DTM implementation.
Implementations that do not know whether attributes are of type ID or
not are expected to return DTM.NULL.
%REVIEW% Presumably IDs are still scoped to a single document,
and this operation searches only within a single document, right?
Wouldn't want collisions between DTMs in the same process. |
public EntityResolver getEntityResolver() {
return this;
}
Return this DTM's EntityResolver. |
public ErrorHandler getErrorHandler() {
return this;
}
Return this DTM's ErrorHandler. |
public String getFixedNames(int type) {
return m_fixednames[type];
}
|
public int getIdForNamespace(String uri) {
return m_valuesOrPrefixes.stringToIndex(uri);
}
Get a prefix either from the uri mapping, or just make
one up! |
public LexicalHandler getLexicalHandler() {
if (m_incrementalSAXSource.getClass()
.getName().equals("com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Filter"))
return (LexicalHandler) m_incrementalSAXSource;
else
return this;
}
Return this DTM's lexical handler.
%REVIEW% Should this return null if constrution already done/begun? |
public String getLocalName(int nodeHandle) {
return m_expandedNameTable.getLocalName(_exptype(makeNodeIdentity(nodeHandle)));
}
Given a node handle, return its XPath-style localname.
(As defined in Namespaces, this is the portion of the name after any
colon character). |
public String getNamespaceURI(int nodeHandle) {
return m_expandedNameTable.getNamespace(_exptype(makeNodeIdentity(nodeHandle)));
}
Given a node handle, return its DOM-style namespace URI
(As defined in Namespaces, this is the declared URI which this node's
prefix -- or default in lieu thereof -- was mapped to.)
%REVIEW% Null or ""? -sb |
public String getNamespaceURI(String prefix) {
String uri = "";
int prefixIndex = m_contextIndexes.peek() - 1 ;
if(null == prefix)
prefix = "";
do
{
prefixIndex = m_prefixMappings.indexOf(prefix, ++prefixIndex);
} while ( (prefixIndex >= 0) && (prefixIndex & 0x01) == 0x01);
if (prefixIndex > -1)
{
uri = (String) m_prefixMappings.elementAt(prefixIndex + 1);
}
return uri;
}
Get a prefix either from the qname or from the uri mapping, or just make
one up! |
protected int getNextNodeIdentity(int identity) {
identity += 1;
while (identity >= m_size)
{
if (null == m_incrementalSAXSource)
return DTM.NULL;
nextNode();
}
return identity;
}
Get the next node identity value in the list, and call the iterator
if it hasn't been added yet. |
public String getNodeName(int nodeHandle) {
int expandedTypeID = getExpandedTypeID(nodeHandle);
// If just testing nonzero, no need to shift...
int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);
if (0 == namespaceID)
{
// Don't retrieve name until/unless needed
// String name = m_expandedNameTable.getLocalName(expandedTypeID);
int type = getNodeType(nodeHandle);
if (type == DTM.NAMESPACE_NODE)
{
if (null == m_expandedNameTable.getLocalName(expandedTypeID))
return "xmlns";
else
return "xmlns:" + m_expandedNameTable.getLocalName(expandedTypeID);
}
else if (0 == m_expandedNameTable.getLocalNameID(expandedTypeID))
{
return m_fixednames[type];
}
else
return m_expandedNameTable.getLocalName(expandedTypeID);
}
else
{
int qnameIndex = m_dataOrQName.elementAt(makeNodeIdentity(nodeHandle));
if (qnameIndex < 0)
{
qnameIndex = -qnameIndex;
qnameIndex = m_data.elementAt(qnameIndex);
}
return m_valuesOrPrefixes.indexToString(qnameIndex);
}
}
Given a node handle, return its DOM-style node name. This will
include names such as #text or #document. |
public String getNodeNameX(int nodeHandle) {
int expandedTypeID = getExpandedTypeID(nodeHandle);
int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);
if (0 == namespaceID)
{
String name = m_expandedNameTable.getLocalName(expandedTypeID);
if (name == null)
return "";
else
return name;
}
else
{
int qnameIndex = m_dataOrQName.elementAt(makeNodeIdentity(nodeHandle));
if (qnameIndex < 0)
{
qnameIndex = -qnameIndex;
qnameIndex = m_data.elementAt(qnameIndex);
}
return m_valuesOrPrefixes.indexToString(qnameIndex);
}
}
Given a node handle, return the XPath node name. This should be
the name as described by the XPath data model, NOT the DOM-style
name. |
public String getNodeValue(int nodeHandle) {
int identity = makeNodeIdentity(nodeHandle);
int type = _type(identity);
if (isTextType(type))
{
int dataIndex = _dataOrQName(identity);
int offset = m_data.elementAt(dataIndex);
int length = m_data.elementAt(dataIndex + 1);
// %OPT% We should cache this, I guess.
return m_chars.getString(offset, length);
}
else if (DTM.ELEMENT_NODE == type || DTM.DOCUMENT_FRAGMENT_NODE == type
|| DTM.DOCUMENT_NODE == type)
{
return null;
}
else
{
int dataIndex = _dataOrQName(identity);
if (dataIndex < 0)
{
dataIndex = -dataIndex;
dataIndex = m_data.elementAt(dataIndex + 1);
}
return m_valuesOrPrefixes.indexToString(dataIndex);
}
}
Given a node handle, return its node value. This is mostly
as defined by the DOM, but may ignore some conveniences.
|
public int getNumberOfNodes() {
return m_size;
}
Get the number of nodes that have been added. |
public String getPrefix(int nodeHandle) {
int identity = makeNodeIdentity(nodeHandle);
int type = _type(identity);
if (DTM.ELEMENT_NODE == type)
{
int prefixIndex = _dataOrQName(identity);
if (0 == prefixIndex)
return "";
else
{
String qname = m_valuesOrPrefixes.indexToString(prefixIndex);
return getPrefix(qname, null);
}
}
else if (DTM.ATTRIBUTE_NODE == type)
{
int prefixIndex = _dataOrQName(identity);
if (prefixIndex < 0)
{
prefixIndex = m_data.elementAt(-prefixIndex);
String qname = m_valuesOrPrefixes.indexToString(prefixIndex);
return getPrefix(qname, null);
}
}
return "";
}
Given a namespace handle, return the prefix that the namespace decl is
mapping.
Given a node handle, return the prefix used to map to the namespace.
%REVIEW% Are you sure you want "" for no prefix?
%REVIEW-COMMENT% I think so... not totally sure. -sb |
public String getPrefix(String qname,
String uri) {
String prefix;
int uriIndex = -1;
if (null != uri && uri.length() > 0)
{
do
{
uriIndex = m_prefixMappings.indexOf(uri, ++uriIndex);
} while ( (uriIndex & 0x01) == 0);
if (uriIndex >= 0)
{
prefix = (String) m_prefixMappings.elementAt(uriIndex - 1);
}
else if (null != qname)
{
int indexOfNSSep = qname.indexOf(':");
if (qname.equals("xmlns"))
prefix = "";
else if (qname.startsWith("xmlns:"))
prefix = qname.substring(indexOfNSSep + 1);
else
prefix = (indexOfNSSep > 0)
? qname.substring(0, indexOfNSSep) : null;
}
else
{
prefix = null;
}
}
else if (null != qname)
{
int indexOfNSSep = qname.indexOf(':");
if (indexOfNSSep > 0)
{
if (qname.startsWith("xmlns:"))
prefix = qname.substring(indexOfNSSep + 1);
else
prefix = qname.substring(0, indexOfNSSep);
}
else
{
if (qname.equals("xmlns"))
prefix = "";
else
prefix = null;
}
}
else
{
prefix = null;
}
return prefix;
}
Get a prefix either from the qname or from the uri mapping, or just make
one up! |
public SourceLocator getSourceLocatorFor(int node) {
if (m_useSourceLocationProperty)
{
node = makeNodeIdentity(node);
return new NodeLocator(null,
m_sourceSystemId.elementAt(node),
m_sourceLine.elementAt(node),
m_sourceColumn.elementAt(node));
}
else if(m_locator!=null)
{
return new NodeLocator(null,m_locator.getSystemId(),-1,-1);
}
else if(m_systemId!=null)
{
return new NodeLocator(null,m_systemId,-1,-1);
}
return null;
}
Retrieve the SourceLocator associated with a specific node.
This is only meaningful if the XalanProperties.SOURCE_LOCATION flag was
set True using setProperty; if it was never set, or was set false, we
will return null.
(We _could_ return a locator with the document's base URI and bogus
line/column information. Trying that; see the else clause.) |
public XMLString getStringValue(int nodeHandle) {
int identity = makeNodeIdentity(nodeHandle);
int type;
if(identity==DTM.NULL) // Separate lines because I wanted to breakpoint it
type = DTM.NULL;
else
type= _type(identity);
if (isTextType(type))
{
int dataIndex = _dataOrQName(identity);
int offset = m_data.elementAt(dataIndex);
int length = m_data.elementAt(dataIndex + 1);
return m_xstrf.newstr(m_chars, offset, length);
}
else
{
int firstChild = _firstch(identity);
if (DTM.NULL != firstChild)
{
int offset = -1;
int length = 0;
int startNode = identity;
identity = firstChild;
do {
type = _type(identity);
if (isTextType(type))
{
int dataIndex = _dataOrQName(identity);
if (-1 == offset)
{
offset = m_data.elementAt(dataIndex);
}
length += m_data.elementAt(dataIndex + 1);
}
identity = getNextNodeIdentity(identity);
} while (DTM.NULL != identity && (_parent(identity) >= startNode));
if (length > 0)
{
return m_xstrf.newstr(m_chars, offset, length);
}
}
else if(type != DTM.ELEMENT_NODE)
{
int dataIndex = _dataOrQName(identity);
if (dataIndex < 0)
{
dataIndex = -dataIndex;
dataIndex = m_data.elementAt(dataIndex + 1);
}
return m_xstrf.newstr(m_valuesOrPrefixes.indexToString(dataIndex));
}
}
return m_xstrf.emptystr();
}
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). |
public String getUnparsedEntityURI(String name) {
String url = "";
if (null == m_entities)
return url;
int n = m_entities.size();
for (int i = 0; i < n; i += ENTITY_FIELDS_PER)
{
String ename = (String) m_entities.elementAt(i + ENTITY_FIELD_NAME);
if (null != ename && ename.equals(name))
{
String nname = (String) m_entities.elementAt(i
+ ENTITY_FIELD_NOTATIONNAME);
if (null != nname)
{
// The draft says: "The XSLT processor may use the public
// identifier to generate a URI for the entity instead of the URI
// specified in the system identifier. If the XSLT processor does
// not use the public identifier to generate the URI, it must use
// the system identifier; if the system identifier is a relative
// URI, it must be resolved into an absolute URI using the URI of
// the resource containing the entity declaration as the base
// URI [RFC2396]."
// So I'm falling a bit short here.
url = (String) m_entities.elementAt(i + ENTITY_FIELD_SYSTEMID);
if (null == url)
{
url = (String) m_entities.elementAt(i + ENTITY_FIELD_PUBLICID);
}
}
break;
}
}
return url;
}
The getUnparsedEntityURI function returns the URI of the unparsed
entity with the specified name in the same document as the context
node (see [3.3 Unparsed Entities]). It returns the empty string if
there is no such entity.
XML processors may choose to use the System Identifier (if one
is provided) to resolve the entity, rather than the URI in the
Public Identifier. The details are dependent on the processor, and
we would have to support some form of plug-in resolver to handle
this properly. Currently, we simply return the System Identifier if
present, and hope that it a usable URI or that our caller can
map it to one.
TODO: Resolve Public Identifiers... or consider changing function name.
If we find a relative URI
reference, XML expects it to be resolved in terms of the base URI
of the document. The DOM doesn't do that for us, and it isn't
entirely clear whether that should be done here; currently that's
pushed up to a higher level of our application. (Note that DOM Level
1 didn't store the document's base URI.)
TODO: Consider resolving Relative URIs.
(The DOM's statement that "An XML processor may choose to
completely expand entities before the structure model is passed
to the DOM" refers only to parsed entities, not unparsed, and hence
doesn't affect this function.) |
public void ignorableWhitespace(char[] ch,
int start,
int length) throws SAXException {
// %OPT% We can probably take advantage of the fact that we know this
// is whitespace.
characters(ch, start, length);
}
Receive notification of ignorable whitespace in element content.
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). |
public void internalEntityDecl(String name,
String value) throws SAXException {
// no op
}
|
public boolean isAttributeSpecified(int attributeHandle) {
// I'm not sure if I want to do anything with this...
return true; // ??
}
5. [specified] A flag indicating whether this attribute was actually
specified in the start-tag of its element, or was defaulted from the
DTD. |
public boolean isWhitespace(int nodeHandle) {
int identity = makeNodeIdentity(nodeHandle);
int type;
if(identity==DTM.NULL) // Separate lines because I wanted to breakpoint it
type = DTM.NULL;
else
type= _type(identity);
if (isTextType(type))
{
int dataIndex = _dataOrQName(identity);
int offset = m_data.elementAt(dataIndex);
int length = m_data.elementAt(dataIndex + 1);
return m_chars.isWhitespace(offset, length);
}
return false;
}
Determine if the string-value of a node is whitespace |
public void migrateTo(DTMManager manager) {
super.migrateTo(manager);
// We have to reset the information in m_dtmIdent and
// register the DTM with the new manager.
int numDTMs = m_dtmIdent.size();
int dtmId = m_mgrDefault.getFirstFreeDTMID();
int nodeIndex = 0;
for (int i = 0; i < numDTMs; i++)
{
m_dtmIdent.setElementAt(dtmId < < DTMManager.IDENT_DTM_NODE_BITS, i);
m_mgrDefault.addDTM(this, dtmId, nodeIndex);
dtmId++;
nodeIndex += (1 < < DTMManager.IDENT_DTM_NODE_BITS);
}
}
Migrate a DTM built with an old DTMManager to a new DTMManager.
After the migration, the new DTMManager will treat the DTM as
one that is built by itself.
This is used to support DTM sharing between multiple transformations. |
public boolean needsTwoThreads() {
return null != m_incrementalSAXSource;
}
|
protected boolean nextNode() {
if (null == m_incrementalSAXSource)
return false;
if (m_endDocumentOccured)
{
clearCoRoutine();
return false;
}
Object gotMore = m_incrementalSAXSource.deliverMoreNodes(true);
// gotMore may be a Boolean (TRUE if still parsing, FALSE if
// EOF) or an exception if IncrementalSAXSource malfunctioned
// (code error rather than user error).
//
// %REVIEW% Currently the ErrorHandlers sketched herein are
// no-ops, so I'm going to initially leave this also as a
// no-op.
if (!(gotMore instanceof Boolean))
{
if(gotMore instanceof RuntimeException)
{
throw (RuntimeException)gotMore;
}
else if(gotMore instanceof Exception)
{
throw new WrappedRuntimeException((Exception)gotMore);
}
// for now...
clearCoRoutine();
return false;
// %TBD%
}
if (gotMore != Boolean.TRUE)
{
// EOF reached without satisfying the request
clearCoRoutine(); // Drop connection, stop trying
// %TBD% deregister as its listener?
}
return true;
}
This method should try and build one or more nodes in the table. |
public void notationDecl(String name,
String publicId,
String systemId) throws SAXException {
// no op
}
Receive notification of a notation declaration.
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. |
public void processingInstruction(String target,
String data) throws SAXException {
if (DEBUG)
System.out.println("processingInstruction: target: " + target +", data: "+data);
charactersFlush();
int exName = m_expandedNameTable.getExpandedTypeID(null, target,
DTM.PROCESSING_INSTRUCTION_NODE);
int dataIndex = m_valuesOrPrefixes.stringToIndex(data);
m_previous = addNode(DTM.PROCESSING_INSTRUCTION_NODE, exName,
m_parents.peek(), m_previous,
dataIndex, false);
}
Receive notification of a processing instruction.
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. |
public InputSource resolveEntity(String publicId,
String systemId) throws SAXException {
return null;
}
Resolve an external entity.
Always return null, so that the parser will use the system
identifier provided in the XML document. This method implements
the SAX default behaviour: application writers can override it
in a subclass to do special translations such as catalog lookups
or URI redirection. |
public void setDocumentLocator(Locator locator) {
m_locator = locator;
m_systemId = locator.getSystemId();
}
Receive a Locator object for document events.
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. |
public void setIDAttribute(String id,
int elem) {
m_idAttributes.put(id, new Integer(elem));
}
Set an ID string to node association in the ID table. |
public void setIncrementalSAXSource(IncrementalSAXSource incrementalSAXSource) {
// Establish coroutine link so we can request more data
//
// Note: It's possible that some versions of IncrementalSAXSource 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
// IncrementalSAXSource.do...() methods.)
m_incrementalSAXSource = incrementalSAXSource;
// Establish SAX-stream link so we can receive the requested data
incrementalSAXSource.setContentHandler(this);
incrementalSAXSource.setLexicalHandler(this);
incrementalSAXSource.setDTDHandler(this);
// Are the following really needed? incrementalSAXSource doesn't yet
// support them, and they're mostly no-ops here...
//incrementalSAXSource.setErrorHandler(this);
//incrementalSAXSource.setDeclHandler(this);
}
Bind a IncrementalSAXSource 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 IncrementalSAXSource, since we don't
know what source it's reading from, what thread that source will run in,
or when it will run. |
public void setProperty(String property,
Object value) {
}
Set a run time property for this DTM instance.
%REVIEW% Now that we no longer use this method to support
getSourceLocatorFor, can we remove it? |
protected void setSourceLocation() {
m_sourceSystemId.addElement(m_locator.getSystemId());
m_sourceLine.addElement(m_locator.getLineNumber());
m_sourceColumn.addElement(m_locator.getColumnNumber());
//%REVIEW% %BUG% Prevent this from arising in the first place
// by not allowing the enabling conditions to change after we start
// building the document.
if (m_sourceSystemId.size() != m_size) {
String msg = "CODING ERROR in Source Location: " + m_size + " != "
+ m_sourceSystemId.size();
System.err.println(msg);
throw new RuntimeException(msg);
}
}
Store the source location of the current node. This method must be called
as every node is added to the DTM or for no node. |
public void setUseSourceLocation(boolean useSourceLocation) {
m_useSourceLocationProperty = useSourceLocation;
}
Set whether information about document source location
should be maintained or not. |
public void skippedEntity(String name) throws SAXException {
// %REVIEW% What should be done here?
// no op
}
Receive notification of a skipped entity.
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. |
public void startCDATA() throws SAXException {
m_textType = DTM.CDATA_SECTION_NODE;
}
|
public void startDTD(String name,
String publicId,
String systemId) throws SAXException {
m_insideDTD = true;
}
Report the start of DTD declarations, if any.
Any declarations are assumed to be in the internal subset
unless otherwise indicated by a startEntity
event.
Note that the start/endDTD events will appear within
the start/endDocument events from ContentHandler and
before the first startElement event. |
public void startDocument() throws SAXException {
if (DEBUG)
System.out.println("startDocument");
int doc = addNode(DTM.DOCUMENT_NODE,
m_expandedNameTable.getExpandedTypeID(DTM.DOCUMENT_NODE),
DTM.NULL, DTM.NULL, 0, true);
m_parents.push(doc);
m_previous = DTM.NULL;
m_contextIndexes.push(m_prefixMappings.size()); // for the next element.
}
Receive notification of the beginning of the document. |
public void startElement(String uri,
String localName,
String qName,
Attributes attributes) throws SAXException {
if (DEBUG)
{
System.out.println("startElement: uri: " + uri + ", localname: "
+ localName + ", qname: "+qName+", atts: " + attributes);
boolean DEBUG_ATTRS=true;
if(DEBUG_ATTRS & 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)
);
}
}
charactersFlush();
int exName = m_expandedNameTable.getExpandedTypeID(uri, localName, DTM.ELEMENT_NODE);
String prefix = getPrefix(qName, uri);
int prefixIndex = (null != prefix)
? m_valuesOrPrefixes.stringToIndex(qName) : 0;
int elemNode = addNode(DTM.ELEMENT_NODE, exName,
m_parents.peek(), m_previous, prefixIndex, true);
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);
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);
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;
String attrLocalName = attributes.getLocalName(i);
if ((null != attrQName)
&& (attrQName.equals("xmlns")
|| attrQName.startsWith("xmlns:")))
{
if (declAlreadyDeclared(prefix))
continue; // go to the next attribute.
nodeType = DTM.NAMESPACE_NODE;
}
else
{
nodeType = DTM.ATTRIBUTE_NODE;
if (attributes.getType(i).equalsIgnoreCase("ID"))
setIDAttribute(valString, elemNode);
}
// 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;
}
exName = m_expandedNameTable.getExpandedTypeID(attrUri, attrLocalName, nodeType);
prev = addNode(nodeType, exName, elemNode, prev, val,
false);
}
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 start of an element.
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). |
public void startEntity(String name) throws SAXException {
// no op
}
Report the beginning of an entity in content.
NOTE: entity references in attribute
values -- and the start and end of the document entity --
are never reported.
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.
Note that skipped entities will be reported through the
skippedEntity
event, which is part of the ContentHandler interface. |
public void startPrefixMapping(String prefix,
String uri) throws SAXException {
if (DEBUG)
System.out.println("startPrefixMapping: prefix: " + prefix + ", uri: "
+ uri);
if(null == prefix)
prefix = "";
m_prefixMappings.addElement(prefix); // JDK 1.1.x compat -sc
m_prefixMappings.addElement(uri); // JDK 1.1.x compat -sc
}
Receive notification of the start of a Namespace mapping.
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). |
public void unparsedEntityDecl(String name,
String publicId,
String systemId,
String notationName) throws SAXException {
if (null == m_entities)
{
m_entities = new Vector();
}
try
{
systemId = SystemIDResolver.getAbsoluteURI(systemId,
getDocumentBaseURI());
}
catch (Exception e)
{
throw new org.xml.sax.SAXException(e);
}
// private static final int ENTITY_FIELD_PUBLICID = 0;
m_entities.addElement(publicId);
// private static final int ENTITY_FIELD_SYSTEMID = 1;
m_entities.addElement(systemId);
// private static final int ENTITY_FIELD_NOTATIONNAME = 2;
m_entities.addElement(notationName);
// private static final int ENTITY_FIELD_NAME = 3;
m_entities.addElement(name);
}
Receive notification of an unparsed entity declaration.
By default, do nothing. Application writers may override this
method in a subclass to keep track of the unparsed entities
declared in a document. |
public void warning(SAXParseException e) throws SAXException {
// %REVIEW% Is there anyway to get the JAXP error listener here?
System.err.println(e.getMessage());
}
Receive notification of a parser warning.
The default implementation does nothing. Application writers
may override this method in a subclass to take specific actions
for each warning, such as inserting the message in a log file or
printing it to the console. |