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

Quick Search    Search Deep

Source code: com/aendvari/common/osm/SimpleOsmPath.java


1   /*
2    * SimpleOsmPath.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.osm;
11  
12  import java.util.Iterator;
13  import java.util.StringTokenizer;
14  
15  import com.aendvari.common.osm.OsmNode;
16  import com.aendvari.common.osm.OsmException;
17  
18  /**
19   * <p>Provides the ability to access nodes within an Object Space Model using an expression.</p>
20   *
21   * <p>This class allows only simple path expressions. It supports the ability to create a node
22   * at the specified path if one does not exist.</p>
23   *
24   * @author  Trevor Milne
25   *
26   */
27  
28  public class SimpleOsmPath
29  {
30    /* Constants. */
31  
32  
33    /** The delimiters used to separate segments of the path expression. */
34    protected static String segmentDelimiters = "./";
35  
36  
37    /* Expressions. */
38  
39  
40    /**
41     * Returns the node at the specified path. Optionally all non existing nodes found
42     * on the path can be created.
43     *
44     * @param    context            The context node specifying the root of the path.
45     * @param    path            Path of the node.
46     * @param    build            True to build non-existing nodes, false will
47     *                      return null if path is not valid.
48     *
49     * @return                  The node found using the path, null if the node cannot be found.
50     *
51     * @exception  OsmException        The operation failed. This method may fail while
52     *                      building non-existing nodes.
53     *
54     */
55  
56    public static OsmNode getNode(OsmNode context, String path, boolean build) throws OsmException
57    {
58      // call different path searches depending on build/no build
59      if (build)
60      {
61        return getNodeBuild(context, path);
62      }
63      else
64      {
65        return getNodeNoBuild(context, path);
66      }
67    }
68  
69    /**
70     * Parses an expression for segments separated by "/" or ".".
71     *
72     */
73  
74    protected static class Tokenizer
75    {
76      /** The current position in the string. */
77      protected int position;
78  
79      /** The string to parse. */
80      protected String expression;
81  
82  
83      /**
84       * Creates a <code>Tokenizer</code> to parse the supplied string.
85       *
86       * @param    setExpression        The expression to parse.
87       *
88       */
89  
90      Tokenizer(String setExpression)
91      {
92        expression = setExpression;
93        position = 0;
94  
95        // ignore leading separator(s)
96        while (position < expression.length())
97        {
98          char letter = expression.charAt(position);
99          if ((letter != '.') && (letter != '/')) break;
100 
101         position++;
102       }
103     }
104 
105     /**
106      * Returns the next available token.
107      *
108      * @return                  The next available token, null if no tokens remain.
109      *
110      */
111 
112     String nextToken()
113     {
114       // check for end of value
115       if (position >= expression.length()) return null;
116 
117       // search for end of next token
118       int nextPosition = position;
119 
120       while (nextPosition < expression.length())
121       {
122         char letter = expression.charAt(nextPosition);
123         if ((letter == '.') || (letter == '/')) break;
124 
125         nextPosition++;
126       }
127 
128       // extract token
129       String token = expression.substring(position, nextPosition);
130 
131       // start next token search at the right of the delimiter
132       position = (nextPosition + 1);
133 
134       return token;
135     }
136   }
137 
138   /**
139    * Returns the node at the specified path. Returns null if the path is not valid.
140    *
141    * @param    parent            The context node specifying the root of the path.
142    * @param    path            Path of the node.
143    *
144    * @return                  The node found using the path.
145    *
146    * @exception  OsmException        The operation failed.
147    *
148    */
149 
150   protected static OsmNode getNodeNoBuild(OsmNode parent, String path) throws OsmException
151   {
152     Tokenizer tokens = new Tokenizer(path);
153 
154     // scan segments of path
155     while (true)
156     {
157       // get next segment
158       String segment = tokens.nextToken();
159 
160       // stop if no segments remain
161       if (segment == null)
162       {
163         break;
164       }
165 
166       // search children for next segment
167       OsmNode children[] = new OsmNode[parent.children.size()];
168       parent.children.toArray(children);
169 
170       // look for new parent
171       parent = null;
172 
173       int childIndex;
174       for (childIndex = 0; childIndex < children.length; childIndex++)
175       {
176         OsmNode child = children[childIndex];
177 
178         // make child new parent if names matches segment
179         if (child.name.equals(segment))
180         {
181           parent = child;
182           break;
183         }
184       }
185 
186       // stop if segment can not be found
187       if (parent == null) break;
188     }
189 
190     return parent;
191   }
192 
193   /**
194    * Returns the node at the specified path. Builds all non existing nodes found
195    * on the path.
196    *
197    * @param    parent            The context node specifying the root of the path.
198    * @param    path            Path of the node.
199    *
200    * @return                  The node found using the path.
201    *
202    * @exception  OsmException        The operation failed.
203    *
204    */
205 
206   protected static OsmNode getNodeBuild(OsmNode parent, String path) throws OsmException
207   {
208     Tokenizer tokens = new Tokenizer(path);
209     String segment = null;
210     OsmNode context = parent;
211 
212     // scan segments of path
213     while (true)
214     {
215       // get next segment
216       segment = tokens.nextToken();
217 
218       // stop if no segments remain
219       if (segment == null)
220       {
221         break;
222       }
223 
224       // search children for next segment
225       OsmNode children[] = new OsmNode[parent.children.size()];
226       parent.children.toArray(children);
227 
228       // look for new parent
229       parent = null;
230 
231       int childIndex;
232       for (childIndex = 0; childIndex < children.length; childIndex++)
233       {
234         OsmNode child = children[childIndex];
235 
236         // make child new parent if names matches segment
237         if (child.name.equals(segment))
238         {
239           parent = child;
240           context = child;
241 
242           break;
243         }
244       }
245 
246       // stop if segment can not be found
247       if (parent == null) break;
248     }
249 
250     // if segment no found, then create nodes for remainder of path
251     if (parent == null)
252     {
253       // restore parent
254       parent = context;
255 
256       // scan remaining segments of path
257       while (true)
258       {
259         // create new node for segment
260         OsmNode newChild = parent.getOwnerOsm().createNode(segment, null);
261         parent.appendChild(newChild);
262 
263         // make child new parent
264         parent = newChild;
265 
266         // get next segment
267         segment = tokens.nextToken();
268 
269         // stop if no segments remain
270         if (segment == null)
271         {
272           break;
273         }
274       }
275     }
276 
277     return parent;
278   }
279 }
280