summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java
blob: a941acb6b71a1ec0b1c8ffadc3002ff881ee80a0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
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 XPath expressions.
	 */
	private static final String XPATH_EXPRESSION_SEPARATOR = "/";

	/**
	 * Current XML node selection character for internal XPath expressions.
	 */
	private static final String XPATH_EXPRESSION_CURRENT_NODE = ".";

	/**
	 * Factory to create 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 XPath expressions.
	 */
	private Node xmlBaseNode = null;

	/**
	 * Create and initialize XPath context to define and compile custom 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 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 XPath
	 *           expressions.
	 */
	public void setXmlBaseNode( Node xmlBaseNode )
	{
		this.xmlBaseNode = xmlBaseNode;
	}

	@Override
	public Node getXmlNode( String expression )
	{
		if ( XPATH_EXPRESSION_CURRENT_NODE.equals( expression ) ) {
			return this.xmlBaseNode;
		}
		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 Element getXmlElement( String expression )
	{
		String completeExpression = null;

		if ( expression == null || 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 (Element)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 ) {
					currentNode = this.xmlDocument.createElement( nodeNames[i] );
					parentNode.appendChild( currentNode );
				}

				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 ) {
			final NodeList childs = node.getChildNodes();
			while ( childs.getLength() > 0 ) {
				Node child = childs.item( 0 );
				node.removeChild( child );
			}
		}
	}

	@Override
	public String getXmlElementAttributeValue( String expression, String attributeName )
	{
		Node node = this.getXmlElement( expression );

		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();
	}
}