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

Quick Search    Search Deep

Source code: com/aendvari/common/model/ModelUtil.java


1   /*
2    * ModelUtil.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;
11  
12  import java.util.Collection;
13  import java.util.Iterator;
14  import java.util.Map;
15  
16  import java.io.Writer;
17  import java.io.StringWriter;
18  import java.io.IOException;
19  
20  import com.aendvari.common.model.*;
21  
22  import com.aendvari.common.osm.*;
23  import com.aendvari.common.model.osm.*;
24  
25  /**
26   * <p>Provides various utility methods for the model classes.</p>
27   *
28   * @author  Scott Milne
29   *
30   */
31  
32  public class ModelUtil
33  {
34    /* Transfer */
35  
36  
37    /**
38     * Updates the children of the specified {@link ModelNode} using the
39     * values stored within other {@link ModelNode ModelNodes}.
40     *
41     * @param    sourceNode          The {@link ModelNode} to read data from.
42     * @param    sourceExpression      An expression selecting the source node.
43     *                      Null to use <code>sourceNode</code>.
44     *
45     * @param    destinationNode        The {@link ModelNode} containing the data to update.
46     * @param    destinationExpression    An expression selecting the destination node.
47     *                      Null to use <code>destinationNode</code>.
48     *
49     * @param    createNodes          True creates destination nodes if they do not exist. False ignores unmatched nodes.
50     *
51     */
52  
53    public static void updateNodes(
54      ModelNode sourceNode, String sourceExpression,
55      ModelNode destinationNode, String destinationExpression,
56      boolean createNodes)
57    {
58      ModelTree sourceTree = sourceNode.getOwnerModelTree();
59      ModelTree destinationTree = destinationNode.getOwnerModelTree();
60  
61      // get root source node
62      ModelNode rootSource = sourceNode;
63  
64      if (sourceExpression != null)
65      {
66        // get specified node
67        rootSource = sourceTree.getNode(sourceNode, sourceExpression);
68  
69        // can not continue if root doesn't exist
70        if (rootSource == null)
71        {
72          throw new ModelException("Node can not be found at '" + sourceExpression + "'.");
73        }
74      }
75  
76      // get root destination node
77      ModelNode rootDestination = destinationNode;
78  
79      if (destinationExpression != null)
80      {
81        // get specified node
82        rootDestination = destinationTree.getNode(destinationNode, destinationExpression);
83  
84        // can not continue if root doesn't exist
85        if (rootDestination == null)
86        {
87          throw new ModelException("Node can not be found at '" + destinationExpression + "'.");
88        }
89      }
90  
91      // the updateNode() method requires that the 'source' node be a child
92      // and that 'destination' be the parent of the similar named child
93  
94      // traverse through the children of the source root and
95      // send to updateNode()
96  
97      Iterator nodeIterator = rootSource.getChildNodes().iterator();
98  
99      while (nodeIterator.hasNext())
100     {
101       ModelNode sourceChild = (ModelNode)nodeIterator.next();
102 
103       // read children and store in children of current destination node
104       updateNode(destinationTree, sourceChild, rootDestination, createNodes);
105     }
106   }
107 
108   /**
109    * Updates the value of the supplied node. Each child node is then recursively
110    * updated.
111    *
112    * @param    destinationTree        The {@link ModelTree} being updated.
113    * @param    sourceNode          The {@link ModelNode} to read data from.
114    * @param    destinationParent      The {@link ModelNode} containing the child to update.
115    * @param    createNodes          True creates destination nodes if they do not exist. False ignores unmatched nodes.
116    *
117    */
118 
119   protected static void updateNode(
120     ModelTree destinationTree, ModelNode sourceNode, ModelNode destinationParent, boolean createNodes)
121   {
122     // use the name of the source node to find the destination node
123     ModelNode updateNode = destinationTree.getNode(destinationParent, sourceNode.getNodeName());
124 
125     // check if node exists
126     if (updateNode == null)
127     {
128       // if not, then create output node if requested
129       if (createNodes)
130       {
131         updateNode = destinationTree.createNode(
132           sourceNode.getNodeName(), sourceNode.getNodeValue());
133       }
134       else
135       {
136         // ignore source value
137         return;
138       }
139     }
140     // if so, then copy value
141     else
142     {
143       // update node value from source node
144       updateNode.setNodeValue(sourceNode.getNodeValue().toString());
145     }
146 
147     // update children
148     Iterator nodeIterator = sourceNode.getChildNodes().iterator();
149 
150     while (nodeIterator.hasNext())
151     {
152       ModelNode sourceChild = (ModelNode)nodeIterator.next();
153 
154       // read children and store in children of current destination node
155       updateNode(destinationTree, sourceChild, updateNode, createNodes);
156     }
157   }
158 
159 
160   /* Deletion */
161 
162 
163   /**
164    * Sets the values of the supplied node and all of its children to an
165    * empty string. Each child is then recursively visited and cleared.
166    *
167    * @param    baseNode          The base {@link ModelNode} of the nodes to clear.
168    *
169    */
170 
171   public static void clearNodes(ModelNode baseNode)
172   {
173     // update node value
174     baseNode.setNodeValue("");
175 
176     // update children
177     Iterator nodeIterator = baseNode.getChildNodes().iterator();
178 
179     while (nodeIterator.hasNext())
180     {
181       ModelNode child = (ModelNode)nodeIterator.next();
182 
183       clearNodes(child);
184     }
185   }
186 
187   /**
188    * Removes the children having the specified name from the supplied node.
189    *
190    * @param    modelNode          The parent {@link ModelNode}.
191    * @param    childName          The name of the children to remove.
192    *
193    */
194 
195   public static void removeNamedChildren(ModelNode modelNode, String childName)
196   {
197     // retrieve list of node name 'childName'
198     Iterator nodeIterator = modelNode.getOwnerModelTree().getNodes(modelNode, childName).iterator();
199 
200     // remove all of the selected nodes from the parent
201     while (nodeIterator.hasNext())
202     {
203       ModelNode entry = (ModelNode)nodeIterator.next();
204       modelNode.removeChild(entry);
205     }
206   }
207 
208   /**
209    * Removes all children of the supplied node.
210    *
211    * @param    modelNode          The parent {@link ModelNode}.
212    *
213    */
214 
215   public static void removeAllChildren(ModelNode modelNode)
216   {
217     // retrieve list of children
218     Iterator nodeIterator = modelNode.getChildNodes().iterator();
219 
220     // remove all children
221     while (nodeIterator.hasNext())
222     {
223       ModelNode entry = (ModelNode)nodeIterator.next();
224       modelNode.removeChild(entry);
225     }
226   }
227 
228   /**
229    * Removes all children of the selected node.
230    *
231    * @param    modelNode          The parent {@link ModelNode}.
232    * @param    selectExpression      An expression selecting a single {@link ModelNode}.
233    *                      Relative to <code>modelNode</code>.
234    *
235    */
236 
237   public static void removeAllChildren(ModelNode modelNode, String selectExpression)
238   {
239     // determine specified node
240     ModelNode removeNode = modelNode.getOwnerModelTree().getNode(modelNode, selectExpression);
241 
242     // check for valid selection
243     if (removeNode == null)
244     {
245       throw new ModelException("Node can not be found at '" + selectExpression + "'.");
246     }
247 
248     // remove children of node
249     removeAllChildren(removeNode);
250   }
251 
252 
253   /* OSM methods */
254 
255 
256   /**
257    * Copies data from the specified location in the supplied {@link Osm OSM} to the
258    * destination {@link ModelNode}.
259    *
260    * @param    sourceNode          The {@link OsmNode} to read data from.
261    * @param    sourceExpression      An expression selecting the source node.
262    *                      Null to use <code>sourceNode</code>.
263    * @param    destinationNode        The {@link ModelNode} containing the data to update.
264    * @param    createNodes          True creates destination nodes if they do not exist. False ignores unmatched nodes.
265    *
266    */
267 
268   public static void osmToModel(
269     OsmNode sourceNode, String sourceExpression, ModelNode destinationNode, boolean createNodes)
270   {
271     OsmNode selectedNode = sourceNode;
272 
273     // select OSM node if expression if provided
274     if (sourceExpression != null)
275     {
276       // select the OSM node
277       selectedNode = SimpleOsmPath.getNode(sourceNode, sourceExpression, false);
278 
279       // check for valid selection
280       if (selectedNode == null)
281       {
282         // if OSM node doesn't exist, then nothing to copy
283         return;
284       }
285     }
286 
287     // create a ModelNode from the selected node
288     OsmModelTree modelTree = new OsmModelTree();
289     ModelNode modelNode = modelTree.createNode(selectedNode);
290 
291     // copy data
292     updateNodes(modelNode, null, destinationNode, null, createNodes);
293   }
294 
295   /**
296    * Copies data from the {@link ModelNode} into the specified location of the
297    * supplied {@link Osm OSM}.
298    *
299    * @param    sourceNode          The {@link ModelNode} to read data from.
300    * @param    destinationNode        The {@link OsmNode} containing the data to update.
301    * @param    destinationExpression    An expression selecting the destination node.
302    *                      Null to use <code>destinationNode</code>.
303    * @param    createNodes          True creates destination nodes if they do not exist. False ignores unmatched nodes.
304    *
305    */
306 
307   public static void modelToOsm(
308     ModelNode sourceNode, OsmNode destinationNode, String destinationExpression, boolean createNodes)
309   {
310     OsmNode selectedNode = destinationNode;
311 
312     // select OSM node if expression if provided
313     if (destinationExpression != null)
314     {
315       // select the OSM node
316       selectedNode = SimpleOsmPath.getNode(destinationNode, destinationExpression, false);
317 
318       // check for valid selection
319       if (selectedNode == null)
320       {
321         throw new ModelException("Node can not be found at '" + destinationExpression + "'.");
322       }
323     }
324 
325     // create a ModelNode from the selected node
326     OsmModelTree modelTree = new OsmModelTree();
327     ModelNode modelNode = modelTree.createNode(selectedNode);
328 
329     // copy data
330     updateNodes(sourceNode, null, modelNode, null, createNodes);
331   }
332 
333 
334   /* Output */
335 
336 
337   /**
338    * Writes the supplied {@link ModelNode} and its children to a string.
339    *
340    * @param    modelNode          The {@link ModelNode} to read data from.
341    *
342    * @return                  A string containing the {@link ModelNode} data.
343    *
344    */
345 
346   public static String writeNode(ModelNode modelNode)
347   {
348     StringWriter buffer = new StringWriter();
349 
350     try
351     {
352       examineNode(modelNode, buffer, "");
353     }
354     catch (IOException exception)
355     {
356       // ignore exception
357     }
358 
359     return buffer.toString();
360   }
361 
362   /**
363    * Writes the supplied {@link ModelNode} and its children to output.
364    *
365    * @param    modelNode          The {@link ModelNode} to read data from.
366    * @param    output            The {@link Writer} to output text to.
367    *
368    * @exception  IOException          Error writing to {@link Writer}.
369    *
370    */
371 
372   public static void writeNode(ModelNode modelNode, Writer output)
373     throws IOException
374   {
375     examineNode(modelNode, output, "");
376   }
377 
378   /**
379    * Outputs a single {@link ModelNode}, then recursively examines children.
380    *
381    * @param    modelNode          The {@link ModelNode} instance to examine.
382    * @param    output            The {@link Writer} to output text to.
383    * @param    indent            The indentation level for the display.
384    *
385    * @exception  IOException          Error writing to {@link Writer}.
386    *
387    */
388 
389   protected static void examineNode(ModelNode modelNode, Writer output, String indent)
390     throws IOException
391   {
392     // start tag
393     output.write(indent);
394     output.write("<");
395     output.write(modelNode.getNodeName());
396 
397     // output attributes
398     Iterator attributeIterator = modelNode.getAttributes().values().iterator();
399 
400     while (attributeIterator.hasNext())
401     {
402       Map.Entry attribute = (Map.Entry)attributeIterator.next();
403 
404       output.write(" ");
405       output.write(attribute.getKey().toString());
406       output.write("=\"");
407       output.write(attribute.getValue().toString());
408       output.write("\"");
409     }
410 
411     output.write(">");
412 
413     // track when a child node has been output
414     boolean childOutput = false;
415 
416     // check for children
417     if (modelNode.hasChildNodes())
418     {
419       // output children
420       Iterator childIterator = modelNode.getChildNodes().iterator();
421 
422       while (childIterator.hasNext())
423       {
424         ModelNode childNode = (ModelNode)childIterator.next();
425 
426         // skip internal nodes
427         if (childNode.getNodeName().startsWith("#")) continue;
428 
429         // start a new line at first child node
430         if (!childOutput)
431         {
432           output.write("\n");
433           childOutput = true;
434         }
435 
436         // examine child
437         examineNode(childNode, output, indent + "    ");
438       }
439 
440       // prepare for close tag
441       if (childOutput)
442       {
443         output.write(indent);
444       }
445     }
446 
447     // check for value
448     if ((modelNode.getNodeValue() != null) && (!childOutput))
449     {
450       // output node value
451       output.write(modelNode.getNodeValue());
452     }
453 
454     // close tag
455     output.write("</");
456     output.write(modelNode.getNodeName());
457     output.write(">\n");
458   }
459 }
460