001 package com.croftsoft.core.text.sml;
002
003 import java.util.Vector;
004
005 import com.croftsoft.core.lang.NullArgumentException;
006 import com.croftsoft.core.text.ParseLib;
007
008 /*********************************************************************
009 * Simplified Markup Language (SML) node.
010 *
011 * <p>
012 * Java 1.1 compatible.
013 * </p>
014 *
015 * @version
016 * 2001-09-12
017 * @since
018 * 2001-03-05
019 * @author
020 * <a href="https://www.croftsoft.com/">David Wallace Croft</a>
021 *********************************************************************/
022
023 public final class SmlNode
024 //////////////////////////////////////////////////////////////////////
025 //////////////////////////////////////////////////////////////////////
026 {
027
028 private static final Object [ ] ZERO_LENGTH_OBJECT_ARRAY
029 = new Object [ ] { };
030
031 private String name;
032
033 private Object [ ] children = ZERO_LENGTH_OBJECT_ARRAY;
034
035 //////////////////////////////////////////////////////////////////////
036 // constructor methods
037 //////////////////////////////////////////////////////////////////////
038
039 public SmlNode ( String name )
040 //////////////////////////////////////////////////////////////////////
041 {
042 NullArgumentException.check ( this.name = name );
043 }
044
045 public SmlNode (
046 String name,
047 String childString )
048 //////////////////////////////////////////////////////////////////////
049 {
050 this ( name );
051
052 if ( childString != null )
053 {
054 add ( childString );
055 }
056 }
057
058 //////////////////////////////////////////////////////////////////////
059 // accessor methods
060 //////////////////////////////////////////////////////////////////////
061
062 public int childCount ( )
063 //////////////////////////////////////////////////////////////////////
064 {
065 return children.length;
066 }
067
068 public String getName ( )
069 //////////////////////////////////////////////////////////////////////
070 {
071 return name;
072 }
073
074 /*********************************************************************
075 * @return
076 * Returns zero-length array if childless; never returns null.
077 *********************************************************************/
078 public Object [ ] getChildren ( )
079 //////////////////////////////////////////////////////////////////////
080 {
081 return children;
082 }
083
084 public Object getChild ( int index )
085 //////////////////////////////////////////////////////////////////////
086 {
087 if ( index >= children.length )
088 {
089 return null;
090 }
091
092 return children [ index ];
093 }
094
095 /*********************************************************************
096 * Returns the first SmlNode child with the given name.
097 *
098 * @return
099 *
100 * May return null.
101 *********************************************************************/
102 public SmlNode getChildNode ( String childNodeName )
103 //////////////////////////////////////////////////////////////////////
104 {
105 NullArgumentException.check ( childNodeName );
106
107 Object [ ] children = this.children;
108
109 for ( int i = 0; i < children.length; i++ )
110 {
111 Object child = children [ i ];
112
113 if ( child instanceof SmlNode )
114 {
115 SmlNode childSmlNode = ( SmlNode ) child;
116
117 if ( childSmlNode.getName ( ).equals ( childNodeName ) )
118 {
119 return childSmlNode;
120 }
121 }
122 }
123
124 return null;
125 }
126
127 /*********************************************************************
128 * Returns all SmlNode children with the given name.
129 *
130 * @return
131 *
132 * May return an empty array.
133 *********************************************************************/
134 public SmlNode [ ] getChildNodes ( String childNodeName )
135 //////////////////////////////////////////////////////////////////////
136 {
137 NullArgumentException.check ( childNodeName );
138
139 Object [ ] children = this.children;
140
141 Vector childNodeVector = new Vector ( );
142
143 for ( int i = 0; i < children.length; i++ )
144 {
145 Object child = children [ i ];
146
147 if ( child instanceof SmlNode )
148 {
149 SmlNode childSmlNode = ( SmlNode ) child;
150
151 if ( childSmlNode.getName ( ).equals ( childNodeName ) )
152 {
153 childNodeVector.addElement ( childSmlNode );
154 }
155 }
156 }
157
158 SmlNode [ ] childNodes = new SmlNode [ childNodeVector.size ( ) ];
159
160 childNodeVector.copyInto ( childNodes );
161
162 return childNodes;
163 }
164
165 /*********************************************************************
166 * return ParseLib.parseBoolean ( getString ( childNodeName ), def );
167 *********************************************************************/
168 public boolean getBoolean ( String childNodeName, boolean def )
169 //////////////////////////////////////////////////////////////////////
170 {
171 return ParseLib.parseBoolean ( getString ( childNodeName ), def );
172 }
173
174 /*********************************************************************
175 * return ParseLib.parseInt ( getString ( childNodeName ), def );
176 *********************************************************************/
177 public int getInt ( String childNodeName, int def )
178 //////////////////////////////////////////////////////////////////////
179 {
180 return ParseLib.parseInt ( getString ( childNodeName ), def );
181 }
182
183 /*********************************************************************
184 * return ParseLib.parseLong ( getString ( childNodeName ), def );
185 *********************************************************************/
186 public long getLong ( String childNodeName, int def )
187 //////////////////////////////////////////////////////////////////////
188 {
189 return ParseLib.parseLong ( getString ( childNodeName ), def );
190 }
191
192 /*********************************************************************
193 * Returns the named child node's first child as cast to a String.
194 *
195 * @return
196 *
197 * May return null.
198 *********************************************************************/
199 public String getString ( String childNodeName )
200 //////////////////////////////////////////////////////////////////////
201 {
202 SmlNode childNode = getChildNode ( childNodeName );
203
204 if ( childNode == null )
205 {
206 return null;
207 }
208
209 return SmlCoder.decode ( ( String ) childNode.getChild ( 0 ) );
210 }
211
212 /*********************************************************************
213 * Finds direct children with the given name and returns their values.
214 *
215 * @return
216 *
217 * May return an empty array.
218 *********************************************************************/
219 public String [ ] getStrings ( String childNodeName )
220 //////////////////////////////////////////////////////////////////////
221 {
222 NullArgumentException.check ( childNodeName );
223
224 Object [ ] children = this.children;
225
226 Vector childStringVector = new Vector ( );
227
228 for ( int i = 0; i < children.length; i++ )
229 {
230 Object child = children [ i ];
231
232 if ( child instanceof SmlNode )
233 {
234 SmlNode childSmlNode = ( SmlNode ) child;
235
236 if ( childSmlNode.getName ( ).equals ( childNodeName ) )
237 {
238 childStringVector.addElement ( SmlCoder.decode (
239 ( String ) childSmlNode.getChild ( 0 ) ) );
240 }
241 }
242 }
243
244 String [ ] strings = new String [ childStringVector.size ( ) ];
245
246 childStringVector.copyInto ( strings );
247
248 return strings;
249 }
250
251 public boolean hasChild ( )
252 //////////////////////////////////////////////////////////////////////
253 {
254 return children.length > 0;
255 }
256
257 //////////////////////////////////////////////////////////////////////
258 // mutator methods
259 //////////////////////////////////////////////////////////////////////
260
261 public void add ( Object smlNodeOrString )
262 //////////////////////////////////////////////////////////////////////
263 {
264 NullArgumentException.check ( smlNodeOrString );
265
266 synchronized ( this )
267 {
268 int childCount = children.length;
269
270 Object [ ] newChildren = new Object [ childCount + 1 ];
271
272 System.arraycopy ( children, 0, newChildren, 0, childCount );
273
274 newChildren [ childCount ] = smlNodeOrString;
275
276 children = newChildren;
277 }
278 }
279
280 public void removeChildren ( )
281 //////////////////////////////////////////////////////////////////////
282 {
283 children = ZERO_LENGTH_OBJECT_ARRAY;
284 }
285
286 //////////////////////////////////////////////////////////////////////
287 // object methods
288 //////////////////////////////////////////////////////////////////////
289
290 public String toString ( )
291 //////////////////////////////////////////////////////////////////////
292 {
293 return toString ( -1, 0 );
294 }
295
296 public String toString ( int indent, int tabSize )
297 //////////////////////////////////////////////////////////////////////
298 {
299 StringBuffer stringBuffer = new StringBuffer ( );
300
301 for ( int i = 0; i < indent; i++ )
302 {
303 stringBuffer.append ( ' ' );
304 }
305
306 stringBuffer.append ( '<' );
307
308 stringBuffer.append ( name );
309
310 Object [ ] children = this.children;
311
312 if ( children.length < 1 )
313 {
314 stringBuffer.append ( "/>" );
315 }
316 else
317 {
318 stringBuffer.append ( ">" );
319
320 Object child = null;
321
322 for ( int i = 0; i < children.length; i++ )
323 {
324 child = children [ i ];
325
326 if ( child instanceof SmlNode )
327 {
328 if ( indent > -1 )
329 {
330 stringBuffer.append ( '\n' );
331 }
332
333 stringBuffer.append ( ( ( SmlNode ) child )
334 .toString ( indent + tabSize, tabSize ) );
335 }
336 else
337 {
338 stringBuffer.append (
339 SmlCoder.encode ( child.toString ( ) ) );
340 }
341 }
342
343 if ( child instanceof SmlNode )
344 {
345 if ( indent > -1 )
346 {
347 stringBuffer.append ( '\n' );
348
349 for ( int i = 0; i < indent; i++ )
350 {
351 stringBuffer.append ( ' ' );
352 }
353 }
354 }
355
356 stringBuffer.append ( "</" );
357
358 stringBuffer.append ( name );
359
360 stringBuffer.append ( ">" );
361 }
362
363 return stringBuffer.toString ( );
364 }
365
366 //////////////////////////////////////////////////////////////////////
367 //////////////////////////////////////////////////////////////////////
368 }