KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > datafile > RecordIterator


1 /*
2  * $Id: RecordIterator.java 5462 2005-08-05 18:35:48Z jonesde $
3  *
4  * Copyright (c) 2001-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  */

25 package org.ofbiz.datafile;
26
27
28 import java.io.BufferedReader JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.io.InputStream JavaDoc;
31 import java.io.InputStreamReader JavaDoc;
32 import java.net.URL JavaDoc;
33 import java.util.Stack JavaDoc;
34
35
36 /**
37  * Record Iterator for reading large files
38  *
39  * @author <a HREF="mailto:jonesde@ofbiz.org">David E. Jones</a>
40  * @version $Rev: 5462 $
41  * @since 3.0
42  */

43
44 public class RecordIterator {
45     
46     public static final String JavaDoc module = RecordIterator.class.getName();
47
48     protected BufferedReader JavaDoc br;
49     protected ModelDataFile modelDataFile;
50     protected InputStream JavaDoc dataFileStream;
51     protected boolean closed = false;
52     protected String JavaDoc locationInfo;
53
54     protected int nextLineNum = 0;
55     protected String JavaDoc curLine = null;
56     protected Record curRecord = null;
57     protected String JavaDoc nextLine = null;
58     protected Record nextRecord = null;
59     
60     public RecordIterator(URL JavaDoc fileUrl, ModelDataFile modelDataFile) throws DataFileException {
61         this.modelDataFile = modelDataFile;
62
63         InputStream JavaDoc urlStream = null;
64         try {
65             urlStream = fileUrl.openStream();
66         } catch (IOException JavaDoc e) {
67             throw new DataFileException("Error open URL: " + fileUrl.toString(), e);
68         }
69         this.setupStream(urlStream, fileUrl.toString());
70     }
71     
72     public RecordIterator(InputStream JavaDoc dataFileStream, ModelDataFile modelDataFile, String JavaDoc locationInfo) throws DataFileException {
73         this.modelDataFile = modelDataFile;
74         this.setupStream(dataFileStream, locationInfo);
75     }
76     
77     protected void setupStream(InputStream JavaDoc dataFileStream, String JavaDoc locationInfo) throws DataFileException {
78         this.locationInfo = locationInfo;
79         this.dataFileStream = dataFileStream;
80         try {
81             this.br = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(dataFileStream, "UTF-8"));
82         } catch(Exception JavaDoc e) {
83             throw new DataFileException("UTF-8 is not supported");
84         }
85
86         // get the line seeded
87
this.getNextLine();
88     }
89     
90     protected boolean getNextLine() throws DataFileException {
91         this.nextLine = null;
92         this.nextRecord = null;
93         
94         boolean isFixedRecord = ModelDataFile.SEP_FIXED_RECORD.equals(modelDataFile.separatorStyle);
95         boolean isFixedLength = ModelDataFile.SEP_FIXED_LENGTH.equals(modelDataFile.separatorStyle);
96         boolean isDelimited = ModelDataFile.SEP_DELIMITED.equals(modelDataFile.separatorStyle);
97         // if (Debug.infoOn()) Debug.logInfo("[DataFile.readDataFile] separatorStyle is " + modelDataFile.separatorStyle + ", isFixedRecord: " + isFixedRecord, module);
98

99         if (isFixedRecord) {
100             if (modelDataFile.recordLength <= 0) {
101                 throw new DataFileException("Cannot read a fixed record length file if no record length is specified");
102             }
103
104             try {
105                 char[] charData = new char[modelDataFile.recordLength + 1];
106
107                 // if (Debug.infoOn()) Debug.logInfo("[DataFile.readDataFile] reading line " + lineNum + " from position " + (lineNum-1)*modelDataFile.recordLength + ", length is " + modelDataFile.recordLength, module);
108
if (br.read(charData, 0, modelDataFile.recordLength) == -1) {
109                     nextLine = null;
110                     // Debug.logInfo("[DataFile.readDataFile] found end of file, got -1", module);
111
} else {
112                     nextLine = new String JavaDoc(charData);
113                     // if (Debug.infoOn()) Debug.logInfo("[DataFile.readDataFile] read line " + lineNum + " line is: \"" + line + "\"", module);
114
}
115             } catch (IOException JavaDoc e) {
116                 throw new DataFileException("Error reading line #" + nextLineNum + " (index " + (nextLineNum - 1) * modelDataFile.recordLength + " length " +
117                         modelDataFile.recordLength + ") from location: " + locationInfo, e);
118             }
119         } else {
120             try {
121                 nextLine = br.readLine();
122             } catch (IOException JavaDoc e) {
123                 throw new DataFileException("Error reading line #" + nextLineNum + " from location: " + locationInfo, e);
124             }
125         }
126         
127         if (nextLine != null) {
128             nextLineNum++;
129             ModelRecord modelRecord = findModelForLine(nextLine, nextLineNum, modelDataFile);
130             if (isDelimited) {
131                 this.nextRecord = Record.createDelimitedRecord(nextLine, nextLineNum, modelRecord, modelDataFile.delimiter);
132             } else {
133                 this.nextRecord = Record.createRecord(nextLine, nextLineNum, modelRecord);
134             }
135             return true;
136         } else {
137             this.close();
138             return false;
139         }
140     }
141     
142     public int getCurrentLineNumber() {
143         return this.nextLineNum - 1;
144     }
145     
146     public boolean hasNext() {
147         return nextLine != null;
148     }
149     
150     public Record next() throws DataFileException {
151         if (!hasNext()) {
152             return null;
153         }
154         
155         if (ModelDataFile.SEP_DELIMITED.equals(modelDataFile.separatorStyle) || ModelDataFile.SEP_FIXED_RECORD.equals(modelDataFile.separatorStyle) || ModelDataFile.SEP_FIXED_LENGTH.equals(modelDataFile.separatorStyle)) {
156             boolean isFixedRecord = ModelDataFile.SEP_FIXED_RECORD.equals(modelDataFile.separatorStyle);
157             // if (Debug.infoOn()) Debug.logInfo("[DataFile.readDataFile] separatorStyle is " + modelDataFile.separatorStyle + ", isFixedRecord: " + isFixedRecord, module);
158

159             // advance the line (we have already checked to make sure there is a next line
160
this.curLine = this.nextLine;
161             this.curRecord = this.nextRecord;
162             
163             // get a new next line
164
this.getNextLine();
165
166             // first check to see if the file type has a line size, and if so if this line complies
167
if (!isFixedRecord && modelDataFile.recordLength > 0 && curLine.length() != modelDataFile.recordLength) {
168                 throw new DataFileException("Line number " + this.getCurrentLineNumber() + " was not the expected length; expected: " + modelDataFile.recordLength + ", got: " + curLine.length());
169             }
170
171             // if this record has children, put it on the parentStack and get/check the children now
172
if (this.curRecord.getModelRecord().childRecords.size() > 0) {
173                 Stack JavaDoc parentStack = new Stack JavaDoc();
174                 parentStack.push(curRecord);
175                 
176                 while (this.nextRecord != null && this.nextRecord.getModelRecord().parentRecord != null) {
177                     // if parent equals top parent on stack, add to that parents child list, otherwise pop off parent and try again
178
Record parentRecord = null;
179
180                     while (parentStack.size() > 0) {
181                         parentRecord = (Record) parentStack.peek();
182                         if (parentRecord.recordName.equals(this.nextRecord.getModelRecord().parentName)) {
183                             break;
184                         } else {
185                             parentStack.pop();
186                             parentRecord = null;
187                         }
188                     }
189
190                     if (parentRecord == null) {
191                         throw new DataFileException("Expected Parent Record not found for line " + this.getCurrentLineNumber() + "; record name of expected parent is " + this.nextRecord.getModelRecord().parentName);
192                     }
193
194                     parentRecord.addChildRecord(this.nextRecord);
195                     
196                     // if the child record we just added is also a parent, push it onto the stack
197
if (this.nextRecord.getModelRecord().childRecords.size() > 0) {
198                         parentStack.push(this.nextRecord);
199                     }
200                         
201                     // if it can't find a next line it will nextRecord will be null and the loop will break out
202
this.getNextLine();
203                 }
204             }
205         } else {
206             throw new DataFileException("Separator style " + modelDataFile.separatorStyle + " not recognized.");
207         }
208         
209         return curRecord;
210     }
211
212     public void close() throws DataFileException {
213         if (this.closed) {
214             return;
215         }
216         try {
217             this.br.close(); // this should also close the stream
218
this.closed = true;
219         } catch (IOException JavaDoc e) {
220             throw new DataFileException("Error closing data file input stream", e);
221         }
222     }
223
224
225     /** Searches through the record models to find one with a matching type-code, if no type-code exists that model will always be used if it gets to it
226      * @param line
227      * @param lineNum
228      * @param modelDataFile
229      * @throws DataFileException Exception thown for various errors, generally has a nested exception
230      * @return
231      */

232     protected static ModelRecord findModelForLine(String JavaDoc line, int lineNum, ModelDataFile modelDataFile) throws DataFileException {
233         // if (Debug.infoOn()) Debug.logInfo("[DataFile.findModelForLine] line: " + line, module);
234
ModelRecord modelRecord = null;
235
236         for (int i = 0; i < modelDataFile.records.size(); i++) {
237             ModelRecord curModelRecord = (ModelRecord) modelDataFile.records.get(i);
238
239             if (curModelRecord.tcPosition < 0) {
240                 modelRecord = curModelRecord;
241                 break;
242             }
243
244             String JavaDoc typeCode = line.substring(curModelRecord.tcPosition, curModelRecord.tcPosition + curModelRecord.tcLength);
245
246             // try to match with a single typecode
247
if (curModelRecord.typeCode.length() > 0) {
248                 // if (Debug.infoOn()) Debug.logInfo("[DataFile.findModelForLine] Doing plain typecode match - code=" + curModelRecord.typeCode + ", filelinecode=" + typeCode, module);
249
if (typeCode != null && typeCode.equals(curModelRecord.typeCode)) {
250                     modelRecord = curModelRecord;
251                     break;
252                 }
253             } // try to match a ranged typecode (tcMin <= typeCode <= tcMax)
254
else if (curModelRecord.tcMin.length() > 0 || curModelRecord.tcMax.length() > 0) {
255                 if (curModelRecord.tcIsNum) {
256                     // if (Debug.infoOn()) Debug.logInfo("[DataFile.findModelForLine] Doing ranged number typecode match - minNum=" + curModelRecord.tcMinNum + ", maxNum=" + curModelRecord.tcMaxNum + ", filelinecode=" + typeCode, module);
257
long typeCodeNum = Long.parseLong(typeCode);
258
259                     if ((curModelRecord.tcMinNum < 0 || typeCodeNum >= curModelRecord.tcMinNum) &&
260                             (curModelRecord.tcMaxNum < 0 || typeCodeNum <= curModelRecord.tcMaxNum)) {
261                         modelRecord = curModelRecord;
262                         break;
263                     }
264                 } else {
265                     // if (Debug.infoOn()) Debug.logInfo("[DataFile.findModelForLine] Doing ranged String typecode match - min=" + curModelRecord.tcMin + ", max=" + curModelRecord.tcMax + ", filelinecode=" + typeCode, module);
266
if ((typeCode.compareTo(curModelRecord.tcMin) >= 0) &&
267                             (typeCode.compareTo(curModelRecord.tcMax) <= 0)) {
268                         modelRecord = curModelRecord;
269                         break;
270                     }
271                 }
272             }
273         }
274         
275         if (modelRecord == null) {
276             throw new DataFileException("Could not find record definition for line " + lineNum + "; first bytes: " +
277                     line.substring(0, (line.length() > 5) ? 5 : line.length()));
278         }
279         // if (Debug.infoOn()) Debug.logInfo("[DataFile.findModelForLine] Got record model named " + modelRecord.name, module);
280
return modelRecord;
281     }
282 }
283
284
Popular Tags