diff options
Diffstat (limited to 'src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java')
-rw-r--r-- | src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java new file mode 100644 index 0000000..93e28de --- /dev/null +++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java @@ -0,0 +1,356 @@ +package org.openslx.libvirt.xml; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * A representation of a XML node as part of a {@link LibvirtXMLDocument}. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class LibvirtXmlNode implements LibvirtXmlCreatable, LibvirtXmlEditable +{ + /** + * Separation character for internal {@link XPath} expressions. + */ + private static final String XPATH_EXPRESSION_SEPARATOR = "/"; + + /** + * Current XML node selection character for internal {@link XPath} expressions. + */ + private static final String XPATH_EXPRESSION_CURRENT_NODE = "."; + + /** + * Factory to create {@link XPath} objects. + */ + private XPathFactory xPathFactory = null; + + /** + * Representation of the XML document, in which this {@link LibvirtXmlNode} is part of. + */ + private Document xmlDocument = null; + + /** + * Current XML base node as XML root anchor for relative internal {@link XPath} expressions. + */ + private Node xmlBaseNode = null; + + /** + * Create and initialize {@link XPath} context to define and compile custom {@link XPath} + * expressions. + */ + private void createXPathContext() + { + this.xPathFactory = XPathFactory.newInstance(); + } + + /** + * Creates empty Libvirt XML node, which does not belong to any XML document and does not specify + * any XML base node. + * + * @implNote Please call {@link LibvirtXmlNode#setXmlDocument(Document)} and + * {@link LibvirtXmlNode#setXmlBaseNode(Node)} manually to obtain a functional Libvirt + * XML node. + */ + public LibvirtXmlNode() + { + this( null, null ); + } + + /** + * Creates Libvirt XML node from a existing Libvirt XML node by reference. + * + * @param xmlNode existing Libvirt XML node. + */ + public LibvirtXmlNode( LibvirtXmlNode xmlNode ) + { + this( xmlNode.getXmlDocument(), xmlNode.getXmlBaseNode() ); + } + + /** + * Creates Libvirt XML node as part of a existing XML document. + * + * @param xmlDocument existing XML document. + * + * @implNote Please call {@link LibvirtXmlNode#setXmlBaseNode(Node)} manually to obtain a + * functional Libvirt XML node. + */ + public LibvirtXmlNode( Document xmlDocument ) + { + this( xmlDocument, null ); + } + + /** + * Creates Libvirt XML node with a specific XML base node. + * + * @param xmlBaseNode existing XML base node. + * + * @implNote Please call {@link LibvirtXmlNode#setXmlDocument(Document)} manually to obtain a + * functional Libvirt XML node. + */ + public LibvirtXmlNode( Node xmlBaseNode ) + { + this( null, xmlBaseNode ); + } + + /** + * Creates Libvirt XML node with a specific XML base node as part of a XML document. + * + * @param xmlDocument existing XML document. + * @param xmlBaseNode existing XML base node. + */ + public LibvirtXmlNode( Document xmlDocument, Node xmlBaseNode ) + { + this.createXPathContext(); + + this.setXmlDocument( xmlDocument ); + this.setXmlBaseNode( xmlBaseNode ); + } + + /** + * Returns referenced XML document. + * + * @return referenced XML document. + */ + public Document getXmlDocument() + { + return this.xmlDocument; + } + + /** + * Sets existing XML document for Libvirt XML node. + * + * @param xmlDocument existing XML document. + */ + public void setXmlDocument( Document xmlDocument ) + { + this.xmlDocument = xmlDocument; + } + + /** + * Returns current XML base node. + * + * @return current XML base node as XML root anchor of relative internal {@link XPath} + * expressions. + */ + public Node getXmlBaseNode() + { + return this.xmlBaseNode; + } + + /** + * Sets existing XML base node for Libvirt XML node. + * + * @param xmlBaseNode existing XML base node as XML root anchor for relative internal + * {@link XPath} expressions. + */ + public void setXmlBaseNode( Node xmlBaseNode ) + { + this.xmlBaseNode = xmlBaseNode; + } + + @Override + public Node getXmlNode( String expression ) + { + NodeList nodes = this.getXmlNodes( expression ); + return nodes.item( 0 ); + } + + @Override + public NodeList getXmlNodes( String expression ) + { + Object nodes = null; + + try { + XPath xPath = this.xPathFactory.newXPath(); + XPathExpression xPathExpr = xPath.compile( expression ); + nodes = xPathExpr.evaluate( this.xmlBaseNode, XPathConstants.NODESET ); + } catch ( XPathExpressionException e ) { + e.printStackTrace(); + } + + return NodeList.class.cast( nodes ); + } + + @Override + public Node getXmlElement( String expression ) + { + String completeExpression = null; + + if ( expression == null ) { + completeExpression = XPATH_EXPRESSION_CURRENT_NODE; + } else if ( expression.isEmpty() ) { + completeExpression = XPATH_EXPRESSION_CURRENT_NODE; + } else { + completeExpression = XPATH_EXPRESSION_CURRENT_NODE + XPATH_EXPRESSION_SEPARATOR + expression; + } + + Node node = this.getXmlNode( completeExpression ); + + if ( node != null && node.getNodeType() == Node.ELEMENT_NODE ) { + return node; + } else { + return null; + } + } + + private Node createXmlElement( String expression ) + { + Node parentNode = this.xmlBaseNode; + Node currentNode = parentNode; + + if ( expression != null && !expression.isEmpty() ) { + String[] nodeNames = expression.split( XPATH_EXPRESSION_SEPARATOR ); + String partialExpression = XPATH_EXPRESSION_CURRENT_NODE; + + for ( int i = 0; i < nodeNames.length; i++ ) { + partialExpression += XPATH_EXPRESSION_SEPARATOR + nodeNames[i]; + currentNode = this.getXmlNode( partialExpression ); + + if ( currentNode == null ) { + parentNode.appendChild( this.xmlDocument.createElement( nodeNames[i] ) ); + currentNode = parentNode.getLastChild(); + } + + parentNode = currentNode; + } + } + + return currentNode; + } + + @Override + public void setXmlElement( String expression, Node child ) + { + Node node = this.createXmlElement( expression ); + + if ( child != null ) { + node.appendChild( child ); + } + } + + @Override + public String getXmlElementValue( String expression ) + { + Node node = this.getXmlElement( expression ); + + if ( node != null ) { + return node.getTextContent(); + } else { + return null; + } + } + + @Override + public void setXmlElementValue( String expression, String value ) + { + Node node = this.createXmlElement( expression ); + node.setTextContent( value ); + } + + @Override + public void removeXmlElement( String expression ) + { + Node node = this.getXmlElement( expression ); + + if ( node != null ) { + node.getParentNode().removeChild( node ); + } + } + + @Override + public void removeXmlElementChilds( String expression ) + { + Node node = this.getXmlElement( expression ); + + if ( node != null ) { + for ( int i = 0; i < node.getChildNodes().getLength(); i++ ) { + Node child = node.getChildNodes().item( 0 ); + node.removeChild( child ); + } + } + } + + @Override + public String getXmlElementAttributeValue( String expression, String attributeName ) + { + Node node = null; + + if ( expression != null && !expression.isEmpty() ) { + node = this.getXmlElement( expression ); + } else { + node = this.xmlBaseNode; + } + + if ( node == null ) { + return null; + } else { + Node attribute = node.getAttributes().getNamedItem( attributeName ); + + if ( attribute == null ) { + return null; + } else { + return attribute.getNodeValue(); + } + } + } + + @Override + public void setXmlElementAttributeValue( String expression, String attributeName, String value ) + { + Node node = this.createXmlElement( expression ); + Node attribute = node.getAttributes().getNamedItem( attributeName ); + + if ( attribute == null ) { + Element element = Element.class.cast( node ); + element.setAttribute( attributeName, value ); + } else { + attribute.setNodeValue( value ); + } + } + + @Override + public void removeXmlElementAttribute( String expression, String attributeName ) + { + Node node = this.getXmlElement( expression ); + + if ( node != null ) { + Node attribute = node.getAttributes().getNamedItem( attributeName ); + node.getAttributes().removeNamedItem( attribute.getNodeName() ); + } + } + + @Override + public void removeXmlElementAttributes( String expression ) + { + Node node = this.getXmlElement( expression ); + + if ( node != null ) { + for ( int i = 0; i < node.getAttributes().getLength(); i++ ) { + Node attribute = node.getAttributes().item( 0 ); + node.getAttributes().removeNamedItem( attribute.getNodeName() ); + } + } + } + + @Override + public void fromXmlNode( Node xmlNode ) + { + this.setXmlBaseNode( xmlNode ); + } + + @Override + public Node toXmlNode() + { + return this.getXmlBaseNode(); + } +} |