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         }