001: /*
002: * $Id: ModelDataFileReader.java,v 1.1 2003/08/19 00:27:10 jonesde Exp $
003: *
004: * Copyright (c) 2001-2003 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: *
024: */
025: package org.ofbiz.datafile;
026:
027: import java.io.IOException;
028: import java.net.URL;
029: import java.util.Collection;
030: import java.util.HashMap;
031: import java.util.Iterator;
032: import java.util.Map;
033:
034: import javax.xml.parsers.ParserConfigurationException;
035:
036: import org.ofbiz.base.util.Debug;
037: import org.ofbiz.base.util.UtilCache;
038: import org.ofbiz.base.util.UtilTimer;
039: import org.ofbiz.base.util.UtilXml;
040: import org.w3c.dom.Document;
041: import org.w3c.dom.Element;
042: import org.w3c.dom.Node;
043: import org.w3c.dom.NodeList;
044: import org.xml.sax.SAXException;
045:
046: /**
047: * Flat File definition reader
048: *
049: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
050: * @version $Revision: 1.1 $
051: * @since 2.0
052: */
053:
054: public class ModelDataFileReader {
055:
056: public static final String module = ModelDataFileReader.class
057: .getName();
058:
059: public static UtilCache readers = new UtilCache("ModelDataFile", 0,
060: 0);
061:
062: public URL readerURL = null;
063: public Map modelDataFiles = null;
064:
065: public static ModelDataFileReader getModelDataFileReader(
066: URL readerURL) {
067: ModelDataFileReader reader = null;
068:
069: reader = (ModelDataFileReader) readers.get(readerURL);
070: if (reader == null) { // don't want to block here
071: synchronized (ModelDataFileReader.class) {
072: // must check if null again as one of the blocked threads can still enter
073: reader = (ModelDataFileReader) readers.get(readerURL);
074: if (reader == null) {
075: if (Debug.infoOn())
076: Debug
077: .logInfo(
078: "[ModelDataFileReader.getModelDataFileReader] : creating reader.",
079: module);
080: reader = new ModelDataFileReader(readerURL);
081: readers.put(readerURL, reader);
082: }
083: }
084: }
085: if (reader != null
086: && (reader.modelDataFiles == null || reader.modelDataFiles
087: .size() == 0)) {
088: readers.remove(readerURL);
089: return null;
090: }
091: if (Debug.infoOn())
092: Debug
093: .logInfo(
094: "[ModelDataFileReader.getModelDataFileReader] : returning reader.",
095: module);
096: return reader;
097: }
098:
099: public ModelDataFileReader(URL readerURL) {
100: this .readerURL = readerURL;
101:
102: // preload models...
103: getModelDataFiles();
104: }
105:
106: public Map getModelDataFiles() {
107: if (modelDataFiles == null) { // don't want to block here
108: synchronized (ModelDataFileReader.class) {
109: // must check if null again as one of the blocked threads can still enter
110: if (modelDataFiles == null) { // now it's safe
111: modelDataFiles = new HashMap();
112:
113: UtilTimer utilTimer = new UtilTimer();
114:
115: utilTimer.timerString("Before getDocument in file "
116: + readerURL);
117: Document document = getDocument(readerURL);
118:
119: if (document == null) {
120: modelDataFiles = null;
121: return null;
122: }
123:
124: utilTimer
125: .timerString("Before getDocumentElement in file "
126: + readerURL);
127: Element docElement = document.getDocumentElement();
128:
129: if (docElement == null) {
130: modelDataFiles = null;
131: return null;
132: }
133: docElement.normalize();
134: Node curChild = docElement.getFirstChild();
135:
136: int i = 0;
137:
138: if (curChild != null) {
139: utilTimer
140: .timerString("Before start of dataFile loop in file "
141: + readerURL);
142: do {
143: if (curChild.getNodeType() == Node.ELEMENT_NODE
144: && "data-file".equals(curChild
145: .getNodeName())) {
146: i++;
147: Element curDataFile = (Element) curChild;
148: String dataFileName = UtilXml
149: .checkEmpty(curDataFile
150: .getAttribute("name"));
151:
152: // check to see if dataFile with same name has already been read
153: if (modelDataFiles
154: .containsKey(dataFileName)) {
155: Debug
156: .logWarning(
157: "WARNING: DataFile "
158: + dataFileName
159: + " is defined more than once, most recent will over-write previous definition(s)",
160: module);
161: }
162:
163: // utilTimer.timerString(" After dataFileName -- " + i + " --");
164: ModelDataFile dataFile = createModelDataFile(curDataFile);
165:
166: // utilTimer.timerString(" After createModelDataFile -- " + i + " --");
167: if (dataFile != null) {
168: modelDataFiles.put(dataFileName,
169: dataFile);
170: // utilTimer.timerString(" After modelDataFiles.put -- " + i + " --");
171: if (Debug.infoOn())
172: Debug
173: .logInfo(
174: "-- getModelDataFile: #"
175: + i
176: + " Loaded dataFile: "
177: + dataFileName,
178: module);
179: } else
180: Debug
181: .logWarning(
182: "-- -- SERVICE ERROR:getModelDataFile: Could not create dataFile for dataFileName: "
183: + dataFileName,
184: module);
185:
186: }
187: } while ((curChild = curChild.getNextSibling()) != null);
188: } else
189: Debug.logWarning("No child nodes found.",
190: module);
191: utilTimer.timerString("Finished file " + readerURL
192: + " - Total Flat File Defs: " + i
193: + " FINISHED");
194: }
195: }
196: }
197: return modelDataFiles;
198: }
199:
200: /** Gets an DataFile object based on a definition from the specified XML DataFile descriptor file.
201: * @param dataFileName The dataFileName of the DataFile definition to use.
202: * @return An DataFile object describing the specified dataFile of the specified descriptor file.
203: */
204: public ModelDataFile getModelDataFile(String dataFileName) {
205: Map ec = getModelDataFiles();
206:
207: if (ec != null)
208: return (ModelDataFile) ec.get(dataFileName);
209: else
210: return null;
211: }
212:
213: /** Creates a Iterator with the dataFileName of each DataFile defined in the specified XML DataFile Descriptor file.
214: * @return A Iterator of dataFileName Strings
215: */
216: public Iterator getDataFileNamesIterator() {
217: Collection collection = getDataFileNames();
218:
219: if (collection != null)
220: return collection.iterator();
221: else
222: return null;
223: }
224:
225: /** Creates a Collection with the dataFileName of each DataFile defined in the specified XML DataFile Descriptor file.
226: * @return A Collection of dataFileName Strings
227: */
228: public Collection getDataFileNames() {
229: Map ec = getModelDataFiles();
230:
231: return ec.keySet();
232: }
233:
234: protected ModelDataFile createModelDataFile(Element dataFileElement) {
235: ModelDataFile dataFile = new ModelDataFile();
236: String tempStr;
237:
238: dataFile.name = UtilXml.checkEmpty(dataFileElement
239: .getAttribute("name"));
240: dataFile.typeCode = UtilXml.checkEmpty(dataFileElement
241: .getAttribute("type-code"));
242: dataFile.sender = UtilXml.checkEmpty(dataFileElement
243: .getAttribute("sender"));
244: dataFile.receiver = UtilXml.checkEmpty(dataFileElement
245: .getAttribute("receiver"));
246:
247: tempStr = UtilXml.checkEmpty(dataFileElement
248: .getAttribute("record-length"));
249: if (tempStr != null && tempStr.length() > 0)
250: dataFile.recordLength = Integer.parseInt(tempStr);
251: tempStr = UtilXml.checkEmpty(dataFileElement
252: .getAttribute("delimiter"));
253: if (tempStr != null && tempStr.length() == 1)
254: dataFile.delimiter = tempStr.charAt(0);
255:
256: dataFile.separatorStyle = UtilXml.checkEmpty(dataFileElement
257: .getAttribute("separator-style"));
258: dataFile.description = UtilXml.checkEmpty(dataFileElement
259: .getAttribute("description"));
260:
261: NodeList rList = dataFileElement.getElementsByTagName("record");
262:
263: for (int i = 0; i < rList.getLength(); i++) {
264: Element recordElement = (Element) rList.item(i);
265: ModelRecord modelRecord = createModelRecord(recordElement);
266:
267: if (modelRecord != null)
268: dataFile.records.add(modelRecord);
269: else
270: Debug
271: .logWarning(
272: "[ModelDataFileReader.createModelDataFile] Weird, modelRecord was null",
273: module);
274: }
275:
276: for (int i = 0; i < dataFile.records.size(); i++) {
277: ModelRecord modelRecord = (ModelRecord) dataFile.records
278: .get(i);
279:
280: if (modelRecord.parentName.length() > 0) {
281: ModelRecord parentRecord = dataFile
282: .getModelRecord(modelRecord.parentName);
283:
284: if (parentRecord != null) {
285: parentRecord.childRecords.add(modelRecord);
286: modelRecord.parentRecord = parentRecord;
287: } else {
288: Debug
289: .logError(
290: "[ModelDataFileReader.createModelDataFile] ERROR: Could not find parentRecord with name "
291: + modelRecord.parentName,
292: module);
293: }
294: }
295: }
296:
297: return dataFile;
298: }
299:
300: protected ModelRecord createModelRecord(Element recordElement) {
301: ModelRecord record = new ModelRecord();
302: String tempStr;
303:
304: record.name = UtilXml.checkEmpty(recordElement
305: .getAttribute("name"));
306: record.typeCode = UtilXml.checkEmpty(recordElement
307: .getAttribute("type-code"));
308:
309: record.tcMin = UtilXml.checkEmpty(recordElement
310: .getAttribute("tc-min"));
311: if (record.tcMin.length() > 0)
312: record.tcMinNum = Long.parseLong(record.tcMin);
313: record.tcMax = UtilXml.checkEmpty(recordElement
314: .getAttribute("tc-max"));
315: if (record.tcMax.length() > 0)
316: record.tcMaxNum = Long.parseLong(record.tcMax);
317:
318: tempStr = UtilXml.checkEmpty(recordElement
319: .getAttribute("tc-isnum"));
320: if (tempStr != null && tempStr.length() > 0)
321: record.tcIsNum = Boolean.valueOf(tempStr).booleanValue();
322:
323: tempStr = UtilXml.checkEmpty(recordElement
324: .getAttribute("tc-position"));
325: if (tempStr != null && tempStr.length() > 0)
326: record.tcPosition = Integer.parseInt(tempStr);
327: tempStr = UtilXml.checkEmpty(recordElement
328: .getAttribute("tc-length"));
329: if (tempStr != null && tempStr.length() > 0)
330: record.tcLength = Integer.parseInt(tempStr);
331:
332: record.description = UtilXml.checkEmpty(recordElement
333: .getAttribute("description"));
334: record.parentName = UtilXml.checkEmpty(recordElement
335: .getAttribute("parent-name"));
336: record.limit = UtilXml.checkEmpty(recordElement
337: .getAttribute("limit"));
338:
339: NodeList fList = recordElement.getElementsByTagName("field");
340: int priorEnd = -1;
341:
342: for (int i = 0; i < fList.getLength(); i++) {
343: Element fieldElement = (Element) fList.item(i);
344: ModelField modelField = createModelField(fieldElement);
345:
346: // if the position is not specified, assume the start position based on last entry
347: if ((i > 0) && (modelField.position == -1)) {
348: modelField.position = priorEnd;
349: }
350: priorEnd = modelField.position + modelField.length;
351:
352: if (modelField != null)
353: record.fields.add(modelField);
354: else
355: Debug
356: .logWarning(
357: "[ModelDataFileReader.createModelRecord] Weird, modelField was null",
358: module);
359: }
360:
361: return record;
362: }
363:
364: protected ModelField createModelField(Element fieldElement) {
365: ModelField field = new ModelField();
366: String tempStr;
367:
368: field.name = UtilXml.checkEmpty(fieldElement
369: .getAttribute("name"));
370:
371: tempStr = UtilXml.checkEmpty(fieldElement
372: .getAttribute("position"));
373: if (tempStr != null && tempStr.length() > 0)
374: field.position = Integer.parseInt(tempStr);
375: tempStr = UtilXml.checkEmpty(fieldElement
376: .getAttribute("length"));
377: if (tempStr != null && tempStr.length() > 0)
378: field.length = Integer.parseInt(tempStr);
379:
380: field.type = UtilXml.checkEmpty(fieldElement
381: .getAttribute("type"));
382: field.format = UtilXml.checkEmpty(fieldElement
383: .getAttribute("format"));
384: field.validExp = UtilXml.checkEmpty(fieldElement
385: .getAttribute("valid-exp"));
386: field.description = UtilXml.checkEmpty(fieldElement
387: .getAttribute("description"));
388:
389: tempStr = UtilXml.checkEmpty(fieldElement
390: .getAttribute("prim-key"));
391: if (tempStr != null && tempStr.length() == 1)
392: field.isPk = Boolean.valueOf(tempStr).booleanValue();
393:
394: return field;
395: }
396:
397: protected Document getDocument(URL url) {
398: if (url == null)
399: return null;
400: Document document = null;
401:
402: try {
403: document = UtilXml.readXmlDocument(url);
404: } catch (SAXException sxe) {
405: // Error generated during parsing)
406: Exception x = sxe;
407:
408: if (sxe.getException() != null)
409: x = sxe.getException();
410: x.printStackTrace();
411: } catch (ParserConfigurationException pce) {
412: // Parser with specified options can't be built
413: pce.printStackTrace();
414: } catch (IOException ioe) {
415: ioe.printStackTrace();
416: }
417:
418: return document;
419: }
420: }
|