Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/aendvari/common/model/xalan/XalanModelNode.java


1   /*
2    * XalanModelNode.java
3    *
4    * Copyright (c) 2001, 2002 Aendvari, Ltd. All Rights Reserved.
5    *
6    * See the file LICENSE for terms of use.
7    *
8    */
9   
10  package com.aendvari.common.model.xalan;
11  
12  import java.util.*;
13  import java.io.*;
14  
15  import org.w3c.dom.Node;
16  import org.w3c.dom.NodeList;
17  import org.w3c.dom.NamedNodeMap;
18  import org.w3c.dom.Attr;
19  
20  import com.aendvari.common.model.*;
21  
22  
23  /**
24   * <p>A Xalan XML implementation of the {@link ModelNode} interface.</p>
25   *
26   * @author  Scott Milne
27   *
28   */
29  
30  public class XalanModelNode implements ModelNode
31  {
32    /* Variables */
33  
34    /** The owning model tree. */
35    protected XalanModelTree owner;
36  
37    /** The DOM node */
38    protected Node modelNode;
39  
40    /** The node value. */
41    protected String modelValue;
42  
43  
44    /* Constructors. */
45  
46  
47    /**
48     * Constructs a <code>XalanModelNode</code> instance.
49     *
50     * @param    setOwner          The owning {@link XalanModelTree}.
51     *
52     */
53  
54    protected XalanModelNode(XalanModelTree setOwner)
55    {
56      owner = setOwner;
57  
58      modelNode = null;
59      modelValue = null;
60    }
61  
62    /**
63     * Constructs a <code>XalanModelNode</code> instance wrapping the supplied {@link Node}.
64     *
65     * @param    setOwner          The owning {@link XalanModelTree}.
66     * @param    setModelNode        The XML {@link Node} to wrap.
67     *
68     */
69  
70    protected XalanModelNode( XalanModelTree setOwner, Node setModelNode )
71    {
72      owner = setOwner;
73  
74      modelNode = setModelNode;
75      setXmlValue();
76    }
77  
78  
79    /* Accessors. */
80  
81  
82    /**
83     * This is used in XalanModelTree::getNode()
84     *
85     * @param    setOwner          The owning {@link XalanModelTree}.
86     *
87     */
88  
89    protected XalanModelNode( XalanModelTree setOwner, String setModelValue )
90    {
91      owner = setOwner;
92  
93      modelNode = null;
94      modelValue = setModelValue;
95    }
96  
97    /**
98     * Sets the internal XML {@link Node} object wrapped by this {@link ModelNode}.
99     *
100    * @param    setModelNode        The XML {@link Node} to wrap.
101    *
102    */
103 
104   public void setXmlNode( Node setModelNode )
105   {
106     modelNode = setModelNode;
107     setXmlValue();
108   }
109 
110   /**
111    * Returns the internal XML {@link Node} object wrapped by this {@link ModelNode}.
112    *
113    * @return                  The XML {@link Node} wrapped by this {@link ModelNode}.
114    *
115    */
116 
117   public Node getXmlNode()
118   {
119     return modelNode;
120   }
121 
122   /**
123    * Caches the value of the XML {@link Node}, if any.
124    *
125    */
126 
127   protected void setXmlValue()
128   {
129     // retrieve value from Node
130     if (modelNode != null)
131     {
132       if (modelNode.getNodeValue() != null)
133         // get the value directly from the node
134         modelValue = modelNode.getNodeValue();
135       else
136         // get the value from the internal text node
137         modelValue = getTextValue();
138     }
139     else
140       modelValue = "";
141   }
142 
143   /**
144    * Returns the instance of <code>ModelTree</code> from which the {@link ModelNode} is within.
145    *
146    * @return                  The {@link ModelTree} instance this node is within.
147    *
148    */
149 
150   public ModelTree getOwnerModelTree()
151   {
152     return owner;
153   }
154 
155   /**
156    * Returns the value of the node.
157    *
158    * @return                  A String value of the node.
159    *
160    */
161 
162   public String getNodeValue()
163   {
164     return modelValue;
165   }
166 
167   /**
168    * Returns the text within the node.
169    *
170    * @return                  The value of the text node within this node.
171    *
172    */
173 
174   protected String getTextValue()
175   {
176     Node node = modelNode.getFirstChild();
177 
178     // scan for first text node
179     while (node != null)
180     {
181       if (node.getNodeType() == Node.TEXT_NODE)
182       {
183         return node.getNodeValue();
184       }
185 
186       node = node.getNextSibling();
187     }
188 
189     return "";
190   }
191 
192   /**
193    * Sets the value of the node.
194    *
195    * @param                  A String value for the node.
196    *
197    */
198 
199   public void setNodeValue( String value )
200   {
201     // state DOM modification
202     owner.setModified();
203 
204     // place value into XML Node
205     if (modelNode != null)
206     {
207       modelNode.setNodeValue(value);
208     }
209 
210     // place value into node string
211     if (value == null)
212       modelValue = "";
213     else
214       modelValue = value;
215   }
216 
217   /**
218    * Returns the name of this node.
219    *
220    * @return                  The name of this node.
221    *
222    */
223 
224   public String getNodeName()
225   {
226     return modelNode.getNodeName();
227   }
228 
229   /**
230    * Returns a string representation of the node's position in the hierarchy.
231    *
232    * @return                  The position of this node in the hierarchy.
233    *
234    */
235 
236   public String getNodePath()
237   {
238     LinkedList nodes = new LinkedList();
239 
240     // traverse node tree upwards, and collect the nodes
241     Node node = modelNode;
242 
243     do
244     {
245       nodes.addFirst(node);
246       node = node.getParentNode();
247     }
248     while (node != null);
249 
250     // traverse back down tree, and create topic path
251     Iterator nodeIterator = nodes.iterator();
252     StringBuffer path = new StringBuffer();
253 
254     // skip the root node
255     nodeIterator.next();
256 
257     while (nodeIterator.hasNext())
258     {
259       // get the node at this level
260       node = (Node)nodeIterator.next();
261 
262       path.append('/');
263       path.append(node.getNodeName());
264     }
265 
266     return path.toString();
267   }
268 
269   /**
270    * Returns the attributes of this node.
271    *
272    * @return                  A <code>Map</code> of all attibutes.
273    *
274    */
275 
276   public Map getAttributes()
277   {
278     HashMap attributes = new HashMap();
279     NamedNodeMap nodeMap = modelNode.getAttributes();
280 
281     if (nodeMap != null)
282     {
283       int count = nodeMap.getLength();
284       int index;
285 
286       // extract each attribute node
287       for (index = 0; index < count; index++)
288       {
289         Node attribute = nodeMap.item(index);
290 
291         // add attribute to output map
292         attributes.put(attribute.getNodeName(), attribute.getNodeValue());
293       }
294     }
295 
296     return attributes;
297   }
298 
299   /**
300    * Returns the string value of the specified attribute.
301    *
302    * @param                  The name of the attribute.
303    *
304    * @return                  The string of the attribute.
305    *
306    */
307 
308   public String getAttribute( String name )
309   {
310     NamedNodeMap nodeMap = modelNode.getAttributes();
311     if( nodeMap != null )
312     {
313       Node attribute = nodeMap.getNamedItem(name);
314       if( attribute != null )
315       {
316         return attribute.getFirstChild().getNodeValue();
317       }
318     }
319 
320     return "";
321   }
322 
323   /**
324    * Sets the string value of the attribute.
325    *
326    * @param    name            The name of the attribute.
327    * @param    value            The value of the attribute.
328    *
329    */
330 
331   public void setAttribute( String name, String value )
332   {
333     // state DOM modification
334     owner.setModified();
335 
336     // retrieve and update attribute
337     NamedNodeMap nodeMap = modelNode.getAttributes();
338 
339     Attr attribute = modelNode.getOwnerDocument().createAttribute(name);
340     attribute.setValue(value);
341 
342     nodeMap.setNamedItem(attribute);
343   }
344 
345 
346   /* Node access. */
347 
348 
349   /**
350    * The parent of this node. All nodes, except the root ({@link ModelNode})
351    * node may have a parent. If a node has just been created and not yet added to the tree, or if
352    * it has been removed from the tree, this is null.
353    *
354    * @return                  The parent of this node.
355    *
356    */
357 
358   public ModelNode getParentNode()
359   {
360     Node parentNode = modelNode.getParentNode();
361 
362     if( parentNode != null )
363     {
364       return new XalanModelNode(owner, parentNode);
365     }
366 
367     return null;
368   }
369 
370   /**
371    * The first child of this node. If there is no such node, this returns null.
372    *
373    * @return                  The first child node.
374    *
375    */
376 
377   public ModelNode getFirstChild()
378   {
379     Node node = modelNode.getFirstChild();
380 
381     if( node != null )
382     {
383       return new XalanModelNode(owner, node);
384     }
385 
386     return null;
387   }
388 
389   /**
390    * The last child of this node. If there is no such node, this returns null.
391    *
392    * @return                  The last child node.
393    *
394    */
395 
396   public ModelNode getLastChild()
397   {
398     Node node = modelNode.getLastChild();
399 
400     if( node != null )
401     {
402       return new XalanModelNode(owner, node);
403     }
404 
405     return null;
406   }
407 
408   /**
409    * The node immediately preceding this node. If there is no such node,
410    * this returns null.
411    *
412    * @return                  The preceding sibling node.
413    *
414    */
415 
416   public ModelNode getPreviousSibling()
417   {
418     Node node = modelNode.getPreviousSibling();
419 
420     if( node != null )
421     {
422       return new XalanModelNode(owner, node);
423     }
424 
425     return null;
426   }
427 
428   /**
429    * The node immediately following this node. If there is no such node,
430    * this returns null.
431    *
432    * @return                  The following sibling node.
433    *
434    */
435 
436   public ModelNode getNextSibling()
437   {
438     Node node = modelNode.getNextSibling();
439 
440     if( node != null )
441     {
442       return new XalanModelNode(owner, node);
443     }
444 
445     return null;
446   }
447 
448   /**
449    * Returns a <code>List</code> of {@link ModelNode}'s using the path provided.
450    *
451    * @return                  A <code>List</code> of this nodes' children as {@link ModelNode}'s.
452    *
453    */
454 
455   public List getChildNodes()
456   {
457     ArrayList xmlNodeList = new ArrayList();
458 
459     Node tmpNode = modelNode.getFirstChild();
460 
461     while (tmpNode != null)
462     {
463       xmlNodeList.add( new XalanModelNode(owner, tmpNode) );
464       tmpNode = tmpNode.getNextSibling();
465     }
466 
467     return xmlNodeList;
468   }
469 
470   /**
471    * Returns whether this node has any children.
472    *
473    * @return                  True if this node has children, false otherwise.
474    *
475    */
476 
477   public boolean hasChildNodes()
478   {
479     return modelNode.hasChildNodes();
480   }
481 
482 
483   /* Node manipulation. */
484 
485 
486   /**
487    * Adds the node <code>newChild</code> to the end of the list of children of this node.
488    * If the <code>newChild</code> is already in the tree, it is first removed.
489    *
490    * @param    newChild          The node to add.
491    *
492    * @return                  The node added.
493    *
494    */
495 
496   public ModelNode appendChild(ModelNode newChild)
497   {
498     // state DOM modification
499     owner.setModified();
500 
501     // append node
502     Node childNode = ((XalanModelNode)newChild).getXmlNode();
503     Node node = modelNode.appendChild(childNode);
504     return new XalanModelNode(owner, node);
505   }
506 
507   /**
508    * Inserts the node <code>newChild</code> before the existing child node <code>refChild</code>.
509    * If <code>refChild</code> is null, <code>newChild</code> is inserted at the end of the list
510    * of children. If the <code>newChild</code> is already in the tree, it is first removed.
511    *
512    * @param    newChild          The node to insert.
513    * @param    refChild          The reference node.
514    *
515    * @return                  The node inserted.
516    *
517    */
518 
519   public ModelNode insertBefore(ModelNode newChild, ModelNode refChild)
520   {
521     // state DOM modification
522     owner.setModified();
523 
524     // insert node
525     Node xNewChild = ((XalanModelNode)newChild).getXmlNode();
526     Node xRefChild = ((XalanModelNode)refChild).getXmlNode();
527 
528     Node node = modelNode.insertBefore(xNewChild, xRefChild);
529     return new XalanModelNode(owner, node);
530   }
531 
532   /**
533    * Replaces the child node <code>oldChild</code> with <code>newChild</code>, and returns
534    * the <code>oldChild</code> node. If the <code>newChild</code> is already in the tree,
535    * it is first removed.
536    *
537    * @param    newChild          The node to replace.
538    * @param    oldChild          The node being replaced.
539    *
540    * @return                  The node replaced.
541    *
542    */
543 
544   public ModelNode replaceChild(ModelNode newChild, ModelNode oldChild)
545   {
546     // state DOM modification
547     owner.setModified();
548 
549     // replaceNode
550     Node xNewChild = ((XalanModelNode)newChild).getXmlNode();
551     Node xOldChild = ((XalanModelNode)oldChild).getXmlNode();
552 
553     Node node = modelNode.replaceChild(xNewChild, xOldChild);
554     return new XalanModelNode(owner, node);
555   }
556 
557   /**
558    * Removes the child node indicated by <code>oldChild</code> from the list of children,
559    * and returns it.
560    *
561    * @param    oldChild          The node to remove.
562    *
563    * @return                  The removed node.
564    *
565    */
566 
567   public ModelNode removeChild(ModelNode oldChild)
568   {
569     // state DOM modification
570     owner.setModified();
571 
572     // remove node
573     Node xOldNode = ((XalanModelNode)oldChild).getXmlNode();
574     Node node = modelNode.removeChild(xOldNode);
575     return new XalanModelNode(owner, node);
576   }
577 
578   /**
579    * Display the string value of the node.
580    *
581    */
582 
583   public String toString()
584   {
585     StringBuffer buffer = new StringBuffer();
586 
587     if (modelNode != null)
588     {
589       buffer.append("name=");
590       buffer.append(getNodeName());
591       buffer.append("; ");
592     }
593 
594     buffer.append("value=" + modelValue);
595 
596     if (modelNode != null)
597     {
598       buffer.append("; node=");
599       buffer.append(modelNode.toString());
600     }
601 
602     return buffer.toString();
603   }
604 }
605