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 }