use of org.exist.numbering.NodeId in project exist by eXist-db.
the class SystemExport method writeXML.
/**
* Serialize a document to XML, based on {@link XMLStreamReader}.
*
* @param doc the document to serialize
* @param receiver the output handler
*/
private void writeXML(final DocumentImpl doc, final Receiver receiver) {
try {
char[] ch;
int nsdecls;
final NamespaceSupport nsSupport = new NamespaceSupport();
final NodeList children = doc.getChildNodes();
final DocumentType docType = doc.getDoctype();
if (docType != null) {
receiver.documentType(docType.getName(), docType.getPublicId(), docType.getSystemId());
}
for (int i = 0; i < children.getLength(); i++) {
final StoredNode child = (StoredNode) children.item(i);
final int thisLevel = child.getNodeId().getTreeLevel();
final int childLevel = child.getNodeType() == Node.ELEMENT_NODE ? thisLevel + 1 : thisLevel;
final XMLStreamReader reader = broker.getXMLStreamReader(child, false);
while (reader.hasNext()) {
final int status = reader.next();
switch(status) {
case XMLStreamReader.START_DOCUMENT:
case XMLStreamReader.END_DOCUMENT:
break;
case XMLStreamReader.START_ELEMENT:
nsdecls = reader.getNamespaceCount();
for (int ni = 0; ni < nsdecls; ni++) {
receiver.startPrefixMapping(reader.getNamespacePrefix(ni), reader.getNamespaceURI(ni));
}
final AttrList attribs = new AttrList();
for (int j = 0; j < reader.getAttributeCount(); j++) {
final QName qn = new QName(reader.getAttributeLocalName(j), reader.getAttributeNamespace(j), reader.getAttributePrefix(j));
attribs.addAttribute(qn, reader.getAttributeValue(j));
}
receiver.startElement(new QName(reader.getLocalName(), reader.getNamespaceURI(), reader.getPrefix()), attribs);
break;
case XMLStreamReader.END_ELEMENT:
receiver.endElement(new QName(reader.getLocalName(), reader.getNamespaceURI(), reader.getPrefix()));
nsdecls = reader.getNamespaceCount();
for (int ni = 0; ni < nsdecls; ni++) {
receiver.endPrefixMapping(reader.getNamespacePrefix(ni));
}
final NodeId otherId = (NodeId) reader.getProperty(ExtendedXMLStreamReader.PROPERTY_NODE_ID);
final int otherLevel = otherId.getTreeLevel();
if (childLevel != thisLevel && otherLevel == thisLevel) {
// exit-while
break;
}
break;
case XMLStreamReader.CHARACTERS:
receiver.characters(reader.getText());
break;
case XMLStreamReader.CDATA:
ch = reader.getTextCharacters();
receiver.cdataSection(ch, 0, ch.length);
break;
case XMLStreamReader.COMMENT:
ch = reader.getTextCharacters();
receiver.comment(ch, 0, ch.length);
break;
case XMLStreamReader.PROCESSING_INSTRUCTION:
receiver.processingInstruction(reader.getPITarget(), reader.getPIData());
break;
}
if (child.getNodeType() == Node.COMMENT_NODE || child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
break;
}
}
nsSupport.reset();
}
} catch (final IOException | SAXException | XMLStreamException e) {
e.printStackTrace();
}
}
use of org.exist.numbering.NodeId in project exist by eXist-db.
the class ConsistencyCheck method checkXMLTree.
/**
* Check the persistent DOM of a document. The method traverses the entire node tree and checks it for consistency, including node relationships,
* child and attribute counts etc.
*
* @param doc the document to check
* @return null if the document is consistent, an error report otherwise.
*/
public ErrorReport checkXMLTree(final DocumentImpl doc) {
final DOMFile domDb = ((NativeBroker) broker).getDOMFile();
return new DOMTransaction<ErrorReport>(this, domDb, () -> broker.getBrokerPool().getLockManager().acquireBtreeWriteLock(domDb.getLockName()), doc) {
public ErrorReport start() {
EmbeddedXMLStreamReader reader = null;
try {
final Node root = doc.getFirstChild();
reader = (EmbeddedXMLStreamReader) broker.getXMLStreamReader((NodeHandle) root, true);
boolean attribsAllowed = false;
int expectedAttribs = 0;
int attributeCount = 0;
while (reader.hasNext()) {
final int status = reader.next();
final NodeId nodeId = (NodeId) reader.getProperty(EmbeddedXMLStreamReader.PROPERTY_NODE_ID);
if ((status != XMLStreamReader.END_ELEMENT) && !elementStack.isEmpty()) {
final ElementNode parent = elementStack.peek();
parent.childCount++;
// test parent-child relation
if (!nodeId.isChildOf(parent.elem.getNodeId())) {
return new ErrorReport.ResourceError(ErrorReport.NODE_HIERARCHY, "Node " + nodeId + " is not a child of " + parent.elem.getNodeId());
}
// test sibling relation
if ((parent.prevSibling != null) && !(nodeId.isSiblingOf(parent.prevSibling) && (nodeId.compareTo(parent.prevSibling) > 0))) {
return new ErrorReport.ResourceError(ErrorReport.INCORRECT_NODE_ID, "Node " + nodeId + " is not a sibling of " + parent.prevSibling);
}
parent.prevSibling = nodeId;
}
switch(status) {
case XMLStreamReader.ATTRIBUTE:
{
attributeCount++;
break;
}
case XMLStreamReader.END_ELEMENT:
{
if (elementStack.isEmpty()) {
return new org.exist.backup.ErrorReport.ResourceError(ErrorReport.NODE_HIERARCHY, "Error in node hierarchy: received END_ELEMENT event " + "but stack was empty!");
}
final ElementNode lastElem = elementStack.pop();
if (lastElem.childCount != lastElem.elem.getChildCount()) {
return new ErrorReport.ResourceError(org.exist.backup.ErrorReport.NODE_HIERARCHY, "Element reports incorrect child count: expected " + lastElem.elem.getChildCount() + " but found " + lastElem.childCount);
}
break;
}
case XMLStreamReader.START_ELEMENT:
{
if (nodeId.getTreeLevel() <= defaultIndexDepth) {
// check dom.dbx btree, which maps the node
// id to the node's storage address
// look up the node id and check if the
// returned storage address is correct
final NativeBroker.NodeRef nodeRef = new NativeBroker.NodeRef(doc.getDocId(), nodeId);
try {
final long p = domDb.findValue(nodeRef);
if (p != reader.getCurrentPosition()) {
final Value v = domDb.get(p);
if (v == null) {
return new ErrorReport.IndexError(ErrorReport.DOM_INDEX, "Failed to access node " + nodeId + " through dom.dbx index. Wrong storage address. Expected: " + p + "; got: " + reader.getCurrentPosition() + " - ", doc.getDocId());
}
}
} catch (final Exception e) {
e.printStackTrace();
return new ErrorReport.IndexError(ErrorReport.DOM_INDEX, "Failed to access node " + nodeId + " through dom.dbx index.", e, doc.getDocId());
}
}
final IStoredNode node = reader.getNode();
if (node.getNodeType() != Node.ELEMENT_NODE) {
return new org.exist.backup.ErrorReport.ResourceError(ErrorReport.INCORRECT_NODE_TYPE, "Expected an element node, received node of type " + node.getNodeType());
}
elementStack.push(new ElementNode((ElementImpl) node));
attribsAllowed = true;
attributeCount = 0;
expectedAttribs = reader.getAttributeCount();
break;
}
default:
{
if (attribsAllowed) {
if (attributeCount != expectedAttribs) {
return new org.exist.backup.ErrorReport.ResourceError(ErrorReport.INCORRECT_NODE_TYPE, "Wrong number of attributes. Expected: " + expectedAttribs + "; found: " + attributeCount);
}
}
attribsAllowed = false;
break;
}
}
}
if (!elementStack.isEmpty()) {
return new org.exist.backup.ErrorReport.ResourceError(ErrorReport.NODE_HIERARCHY, "Error in node hierarchy: reached end of tree but " + "stack was not empty!");
}
return null;
} catch (final IOException | XMLStreamException e) {
e.printStackTrace();
return new org.exist.backup.ErrorReport.ResourceError(ErrorReport.RESOURCE_ACCESS_FAILED, e.getMessage(), e);
} finally {
elementStack.clear();
if (reader != null) {
try {
reader.close();
} catch (final XMLStreamException e) {
e.printStackTrace();
}
}
}
}
}.run();
}
use of org.exist.numbering.NodeId in project exist by eXist-db.
the class NodeImpl method selectPreceding.
public void selectPreceding(final NodeTest test, final Sequence result, final int position) throws XPathException {
final NodeId myNodeId = getNodeId();
int count = 0;
for (int i = nodeNumber - 1; i > 0; i--) {
final NodeImpl n = document.getNode(i);
if (!myNodeId.isDescendantOf(n.getNodeId()) && test.matches(n)) {
if ((position < 0) || (++count == position)) {
result.add(n);
}
if (count == position) {
break;
}
}
}
}
use of org.exist.numbering.NodeId in project exist by eXist-db.
the class ElementImpl method getChildren.
private void getChildren(final boolean includeAttributes, final org.exist.dom.NodeListImpl childList) {
try (final DBBroker broker = ownerDocument.getBrokerPool().getBroker()) {
final int thisLevel = nodeId.getTreeLevel();
final int childLevel = thisLevel + 1;
for (final IEmbeddedXMLStreamReader reader = broker.getXMLStreamReader(this, includeAttributes); reader.hasNext(); ) {
final int status = reader.next();
final NodeId otherId = (NodeId) reader.getProperty(ExtendedXMLStreamReader.PROPERTY_NODE_ID);
final int otherLevel = otherId.getTreeLevel();
// skip descendants
if (otherLevel > childLevel) {
continue;
}
if (status == XMLStreamConstants.END_ELEMENT) {
if (otherLevel == thisLevel) {
// exit-for
break;
}
// skip over any other END_ELEMENT(s)
} else {
if (otherLevel == childLevel) {
// child
childList.add(reader.getNode());
}
}
}
} catch (final IOException | XMLStreamException | EXistException e) {
LOG.warn("Internal error while reading child nodes: {}", e.getMessage(), e);
}
}
use of org.exist.numbering.NodeId in project exist by eXist-db.
the class ElementImpl method deserialize.
public static StoredNode deserialize(final byte[] data, final int start, final int len, final DocumentImpl doc, final boolean pooled) {
final int end = start + len;
int pos = start;
final byte idSizeType = (byte) (data[pos] & 0x03);
boolean isDirty = (data[pos] & 0x8) == 0x8;
final boolean hasNamespace = (data[pos] & 0x10) == 0x10;
pos += StoredNode.LENGTH_SIGNATURE_LENGTH;
final int children = ByteConversion.byteToInt(data, pos);
pos += LENGTH_ELEMENT_CHILD_COUNT;
final int dlnLen = ByteConversion.byteToShort(data, pos);
pos += NodeId.LENGTH_NODE_ID_UNITS;
final NodeId dln = doc.getBrokerPool().getNodeFactory().createFromData(dlnLen, data, pos);
pos += dln.size();
final short attributes = ByteConversion.byteToShort(data, pos);
pos += LENGTH_ATTRIBUTES_COUNT;
final short id = (short) Signatures.read(idSizeType, data, pos);
pos += Signatures.getLength(idSizeType);
short nsId = 0;
String prefix = null;
if (hasNamespace) {
nsId = ByteConversion.byteToShort(data, pos);
pos += LENGTH_NS_ID;
int prefixLen = ByteConversion.byteToShort(data, pos);
pos += LENGTH_PREFIX_LENGTH;
if (prefixLen > 0) {
prefix = UTF8.decode(data, pos, prefixLen).toString();
}
pos += prefixLen;
}
final String name = doc.getBrokerPool().getSymbols().getName(id);
String namespace = XMLConstants.NULL_NS_URI;
if (nsId != 0) {
namespace = doc.getBrokerPool().getSymbols().getNamespace(nsId);
}
final ElementImpl node;
if (pooled) {
node = (ElementImpl) NodePool.getInstance().borrowNode(Node.ELEMENT_NODE);
} else {
node = new ElementImpl();
}
node.setNodeId(dln);
node.nodeName = doc.getBrokerPool().getSymbols().getQName(Node.ELEMENT_NODE, namespace, name, prefix);
node.children = children;
node.attributes = attributes;
node.isDirty = isDirty;
node.setOwnerDocument(doc);
// TO UNDERSTAND : why is this code here ?
if (end > pos) {
final byte[] pfxData = new byte[end - pos];
System.arraycopy(data, pos, pfxData, 0, end - pos);
final InputStream bin = new UnsynchronizedByteArrayInputStream(pfxData);
final DataInputStream in = new DataInputStream(bin);
try {
final short prefixCount = in.readShort();
for (int i = 0; i < prefixCount; i++) {
prefix = in.readUTF();
nsId = in.readShort();
node.addNamespaceMapping(prefix, doc.getBrokerPool().getSymbols().getNamespace(nsId));
}
} catch (final IOException e) {
LOG.error(e);
}
}
return node;
}
Aggregations