001         package com.croftsoft.core.text.sml;
002    
003         import java.io.*;
004         import java.util.*;
005         import java.util.zip.*;
006         import javax.xml.parsers.*;
007         import org.xml.sax.*;
008         import org.xml.sax.helpers.*;
009    
010         import com.croftsoft.core.lang.NullArgumentException;
011    import com.croftsoft.core.text.sml.SmlNode;
012    import com.croftsoft.core.util.consumer.Consumer;
013    
014         /*********************************************************************
015         * Used to parse large SML files one data record at a time.
016         *
017         * <p>
018         * This class is similar to SmlNodeLoader except that is uses an XML
019         * parser instead of the SML parser.
020         * </p>
021         *
022         * @version
023         *   2002-09-24
024         * @since
025         *   2002-09-18
026         * @author
027         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
028         *********************************************************************/
029    
030         public final class  SmlRecordLoader
031           extends DefaultHandler
032         //////////////////////////////////////////////////////////////////////
033         //////////////////////////////////////////////////////////////////////
034         {
035    
036         private final Consumer  smlRecordConsumer;
037    
038         private final Stack     parentNodeStack;
039    
040         //
041    
042         private int      depth;
043    
044         private SmlNode  smlNode;
045    
046         //////////////////////////////////////////////////////////////////////
047         //////////////////////////////////////////////////////////////////////
048    
049         public static void  main ( String [ ]  args )
050           throws Exception
051         //////////////////////////////////////////////////////////////////////
052         {
053           parse (
054             args [ 0 ],
055             new Consumer ( )
056             {
057               public void  consume ( Object  o )
058               {
059                 System.out.println ( o );
060    
061                 System.out.println ( "" );
062               }
063             },
064             args [ 0 ].toLowerCase ( ).endsWith ( ".zip"  ),
065             args [ 0 ].toLowerCase ( ).endsWith ( ".gz"   ) );
066         }
067    
068         //////////////////////////////////////////////////////////////////////
069         //////////////////////////////////////////////////////////////////////
070    
071         public static void  parse (
072           InputSource  inputSource,
073           Consumer     smlRecordConsumer )
074           throws IOException, ParserConfigurationException, SAXException
075         //////////////////////////////////////////////////////////////////////
076         {
077           NullArgumentException.check ( inputSource );
078    
079           NullArgumentException.check ( smlRecordConsumer );
080    
081           SAXParserFactory  saxParserFactory
082             = SAXParserFactory.newInstance ( );
083    
084           SAXParser  saxParser = saxParserFactory.newSAXParser ( );
085    
086           saxParser.parse (
087             inputSource, new SmlRecordLoader ( smlRecordConsumer ) );
088         }
089    
090         public static void  parse (
091           String    smlDataFilename,
092           Consumer  smlRecordConsumer,
093           boolean   isZipFile,
094           boolean   isGzipFile )
095           throws IOException, ParserConfigurationException, SAXException
096         //////////////////////////////////////////////////////////////////////
097         {
098           InputStream  inputStream = null;
099    
100           try
101           {
102             inputStream = new FileInputStream ( smlDataFilename );
103    
104             if ( isZipFile )
105             {
106               ZipInputStream  zipInputStream
107                 = new ZipInputStream ( inputStream );
108    
109               zipInputStream.getNextEntry ( );
110    
111               inputStream = zipInputStream;
112             }
113             else if ( isGzipFile )
114             {
115               inputStream = new GZIPInputStream ( inputStream );
116             }
117    
118             InputSource  inputSource = new InputSource (
119               new BufferedReader ( new InputStreamReader ( inputStream ) ) );
120    
121             parse ( inputSource, smlRecordConsumer );
122           }
123           finally
124           {
125             if ( inputStream != null )
126             {
127               inputStream.close ( );
128             }
129           }
130         }
131    
132         //////////////////////////////////////////////////////////////////////
133         //////////////////////////////////////////////////////////////////////
134    
135         private  SmlRecordLoader ( Consumer  smlRecordConsumer )
136         //////////////////////////////////////////////////////////////////////
137         {
138           NullArgumentException.check (
139             this.smlRecordConsumer = smlRecordConsumer );
140    
141           parentNodeStack = new Stack ( );
142         }
143    
144         //////////////////////////////////////////////////////////////////////
145         //////////////////////////////////////////////////////////////////////
146    
147         public void  startElement (
148           String      namespaceURI,
149           String      localName,
150           String      qName,
151           Attributes  atts )
152         //////////////////////////////////////////////////////////////////////
153         {
154             depth++;
155    
156             if ( depth == 2 )
157             {
158               smlNode = new SmlNode ( qName );
159             }
160             else if ( depth > 2 )
161             {
162               SmlNode  childNode = new SmlNode ( qName );
163    
164               Object  firstChild = smlNode.getChild ( 0 );
165    
166               if ( firstChild instanceof String )
167               {
168                 smlNode.getChildren ( ) [ 0 ] = childNode;
169               }
170               else
171               {
172                 smlNode.add ( childNode );
173               }
174    
175               parentNodeStack.push ( smlNode );
176    
177               smlNode = childNode;
178             }
179         }
180    
181         public void  characters (
182           char [ ]  ch,
183           int       start,
184           int       length )
185         //////////////////////////////////////////////////////////////////////
186         {
187             if ( smlNode != null )
188             {
189               Object  firstChild = smlNode.getChild ( 0 );
190    
191               if ( firstChild == null )
192               {
193                 smlNode.add ( new String ( ch, start, length ) );
194               }
195               else if ( firstChild instanceof String )
196               {
197                 smlNode.getChildren ( ) [ 0 ]
198                   = firstChild + new String ( ch, start, length );
199               }
200             }
201         }
202    
203         public void  endElement (
204           String      namespaceURI,
205           String      localName,
206           String      qName )
207         //////////////////////////////////////////////////////////////////////
208         {
209             depth--;
210    
211             if ( depth > 1 )
212             {
213               smlNode = ( SmlNode ) parentNodeStack.pop ( );
214             }
215             else if ( depth == 1 )
216             {
217               smlRecordConsumer.consume ( smlNode );
218    
219               smlNode = null;
220             }
221         }
222    
223    /*
224         public void  error ( SAXParseException  e )
225           throws SAXException
226         //////////////////////////////////////////////////////////////////////
227         {
228    System.out.println ( "Parse error on node " + smlNode );
229    
230           super.error ( e );
231         }
232    
233         public void  fatalError ( SAXParseException  e )
234           throws SAXException
235         //////////////////////////////////////////////////////////////////////
236         {
237    System.out.println ( "Fatal parse error on node " + smlNode );
238    
239           super.fatalError ( e );
240         }
241    */
242    
243         //////////////////////////////////////////////////////////////////////
244         //////////////////////////////////////////////////////////////////////
245         }