| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| *******************************************************************************/ |
| package org.ofbiz.datafile; |
| |
| import java.net.URL; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.ofbiz.base.util.Debug; |
| import org.ofbiz.base.util.UtilValidate; |
| import org.ofbiz.base.util.UtilXml; |
| import org.ofbiz.base.util.cache.UtilCache; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NodeList; |
| |
| /** |
| * Flat File definition reader |
| */ |
| |
| public final class ModelDataFileReader { |
| |
| public static final String module = ModelDataFileReader.class.getName(); |
| private static final UtilCache<URL, ModelDataFileReader> readers = UtilCache.createUtilCache("ModelDataFile", true); |
| |
| public static ModelDataFileReader getModelDataFileReader(URL readerURL) throws DataFileException { |
| ModelDataFileReader reader = readers.get(readerURL); |
| if (reader == null) { |
| if (Debug.infoOn()) |
| Debug.logInfo("[ModelDataFileReader.getModelDataFileReader] : creating reader for " + readerURL, module); |
| reader = new ModelDataFileReader(readerURL); |
| readers.putIfAbsent(readerURL, reader); |
| } |
| if (Debug.infoOn()) |
| Debug.logInfo("[ModelDataFileReader.getModelDataFileReader] : returning reader for " + readerURL, module); |
| return reader; |
| } |
| |
| private final URL readerURL; |
| private final Map<String, ModelDataFile> modelDataFiles; |
| |
| public ModelDataFileReader(URL readerURL) throws DataFileException { |
| this.readerURL = readerURL; |
| this.modelDataFiles = Collections.unmodifiableMap(createModelDataFiles()); |
| } |
| |
| private ModelDataFile createModelDataFile(Element dataFileElement) { |
| ModelDataFile dataFile = new ModelDataFile(); |
| String tempStr; |
| |
| dataFile.name = UtilXml.checkEmpty(dataFileElement.getAttribute("name")); |
| dataFile.typeCode = UtilXml.checkEmpty(dataFileElement.getAttribute("type-code")); |
| dataFile.sender = UtilXml.checkEmpty(dataFileElement.getAttribute("sender")); |
| dataFile.receiver = UtilXml.checkEmpty(dataFileElement.getAttribute("receiver")); |
| |
| tempStr = UtilXml.checkEmpty(dataFileElement.getAttribute("record-length")); |
| if (UtilValidate.isNotEmpty(tempStr)) { |
| dataFile.recordLength = Integer.parseInt(tempStr); |
| } |
| tempStr = UtilXml.checkEmpty(dataFileElement.getAttribute("delimiter")); |
| if (tempStr != null && tempStr.length() == 1) { |
| dataFile.delimiter = tempStr.charAt(0); |
| } |
| |
| tempStr = UtilXml.checkEmpty(dataFileElement.getAttribute("text-delimiter")); |
| if (UtilValidate.isNotEmpty(tempStr)) { |
| dataFile.textDelimiter = tempStr; |
| } |
| |
| dataFile.separatorStyle = UtilXml.checkEmpty(dataFileElement.getAttribute("separator-style")); |
| dataFile.description = UtilXml.checkEmpty(dataFileElement.getAttribute("description")); |
| |
| NodeList rList = dataFileElement.getElementsByTagName("record"); |
| |
| for (int i = 0; i < rList.getLength(); i++) { |
| Element recordElement = (Element) rList.item(i); |
| ModelRecord modelRecord = createModelRecord(recordElement); |
| |
| if (modelRecord != null) { |
| dataFile.records.add(modelRecord); |
| } else { |
| Debug.logWarning("[ModelDataFileReader.createModelDataFile] Weird, modelRecord was null", module); |
| } |
| } |
| |
| for (ModelRecord modelRecord : dataFile.records) { |
| |
| if (modelRecord.parentName.length() > 0) { |
| ModelRecord parentRecord = dataFile.getModelRecord(modelRecord.parentName); |
| |
| if (parentRecord != null) { |
| parentRecord.childRecords.add(modelRecord); |
| modelRecord.parentRecord = parentRecord; |
| } else { |
| Debug.logError("[ModelDataFileReader.createModelDataFile] ERROR: Could not find parentRecord with name " + modelRecord.parentName, module); |
| } |
| } |
| } |
| |
| return dataFile; |
| } |
| |
| private Map<String, ModelDataFile> createModelDataFiles() throws DataFileException { |
| Document document = null; |
| Element docElement = null; |
| try { |
| document = UtilXml.readXmlDocument(this.readerURL); |
| } catch (Exception e) { |
| Debug.logWarning(e, "Error while reading " + this.readerURL + ": ", module); |
| throw new DataFileException("Error while reading " + this.readerURL, e); |
| } |
| if (document != null) { |
| docElement = document.getDocumentElement(); |
| } |
| if (docElement == null) { |
| Debug.logWarning("Document element not found in " + this.readerURL, module); |
| throw new DataFileException("Document element not found in " + this.readerURL); |
| } |
| docElement.normalize(); |
| List<? extends Element> dataFileElements = UtilXml.childElementList(docElement, "data-file"); |
| if (dataFileElements.size() == 0) { |
| Debug.logWarning("No <data-file> elements found in " + this.readerURL, module); |
| throw new DataFileException("No <data-file> elements found in " + this.readerURL); |
| } |
| Map<String, ModelDataFile> result = new HashMap<String, ModelDataFile>(); |
| for (Element curDataFile : dataFileElements) { |
| String dataFileName = UtilXml.checkEmpty(curDataFile.getAttribute("name")); |
| if (result.containsKey(dataFileName)) { |
| Debug.logWarning("DataFile " + dataFileName + " is defined more than once, most recent will over-write previous definition(s)", module); |
| } |
| ModelDataFile dataFile = createModelDataFile(curDataFile); |
| if (dataFile != null) { |
| result.put(dataFileName, dataFile); |
| if (Debug.verboseOn()) { |
| Debug.logVerbose("Loaded dataFile: " + dataFileName, module); |
| } |
| } else { |
| Debug.logWarning("Could not create dataFile for dataFileName " + dataFileName, module); |
| throw new DataFileException("Could not create dataFile for " + dataFileName + " defined in " + this.readerURL); |
| } |
| } |
| return result; |
| } |
| |
| private ModelField createModelField(Element fieldElement) { |
| ModelField field = new ModelField(); |
| String tempStr; |
| |
| field.name = UtilXml.checkEmpty(fieldElement.getAttribute("name")); |
| |
| tempStr = UtilXml.checkEmpty(fieldElement.getAttribute("position")); |
| if (UtilValidate.isNotEmpty(tempStr)) { |
| field.position = Integer.parseInt(tempStr); |
| } |
| tempStr = UtilXml.checkEmpty(fieldElement.getAttribute("length")); |
| if (UtilValidate.isNotEmpty(tempStr)) { |
| field.length = Integer.parseInt(tempStr); |
| } |
| |
| field.type = UtilXml.checkEmpty(fieldElement.getAttribute("type")); |
| field.format = UtilXml.checkEmpty(fieldElement.getAttribute("format")); |
| field.validExp = UtilXml.checkEmpty(fieldElement.getAttribute("valid-exp")); |
| field.description = UtilXml.checkEmpty(fieldElement.getAttribute("description")); |
| field.defaultValue = UtilXml.checkEmpty(fieldElement.getAttribute("default-value")); |
| field.refField = UtilXml.checkEmpty(fieldElement.getAttribute("ref-field")); |
| |
| tempStr = UtilXml.checkEmpty(fieldElement.getAttribute("prim-key")); |
| if (UtilValidate.isNotEmpty(tempStr)) { |
| field.isPk = Boolean.parseBoolean(tempStr); |
| } |
| |
| tempStr = UtilXml.checkEmpty(fieldElement.getAttribute("ignored")); |
| if (UtilValidate.isNotEmpty(tempStr)) { |
| field.ignored = Boolean.parseBoolean(tempStr); |
| } |
| |
| tempStr = UtilXml.checkEmpty(fieldElement.getAttribute("expression")); |
| if (UtilValidate.isNotEmpty(tempStr)) { |
| field.expression = Boolean.parseBoolean(tempStr); |
| } |
| |
| return field; |
| } |
| |
| private ModelRecord createModelRecord(Element recordElement) { |
| ModelRecord record = new ModelRecord(); |
| String tempStr; |
| |
| record.name = UtilXml.checkEmpty(recordElement.getAttribute("name")); |
| record.typeCode = UtilXml.checkEmpty(recordElement.getAttribute("type-code")); |
| |
| record.tcMin = UtilXml.checkEmpty(recordElement.getAttribute("tc-min")); |
| if (record.tcMin.length() > 0) |
| record.tcMinNum = Long.parseLong(record.tcMin); |
| record.tcMax = UtilXml.checkEmpty(recordElement.getAttribute("tc-max")); |
| if (record.tcMax.length() > 0) |
| record.tcMaxNum = Long.parseLong(record.tcMax); |
| |
| tempStr = UtilXml.checkEmpty(recordElement.getAttribute("tc-isnum")); |
| if (UtilValidate.isNotEmpty(tempStr)) { |
| record.tcIsNum = Boolean.parseBoolean(tempStr); |
| } |
| |
| tempStr = UtilXml.checkEmpty(recordElement.getAttribute("tc-position")); |
| if (UtilValidate.isNotEmpty(tempStr)) { |
| record.tcPosition = Integer.parseInt(tempStr); |
| } |
| tempStr = UtilXml.checkEmpty(recordElement.getAttribute("tc-length")); |
| if (UtilValidate.isNotEmpty(tempStr)) { |
| record.tcLength = Integer.parseInt(tempStr); |
| } |
| |
| record.description = UtilXml.checkEmpty(recordElement.getAttribute("description")); |
| record.parentName = UtilXml.checkEmpty(recordElement.getAttribute("parent-name")); |
| record.limit = UtilXml.checkEmpty(recordElement.getAttribute("limit")); |
| |
| NodeList fList = recordElement.getElementsByTagName("field"); |
| int priorEnd = -1; |
| |
| for (int i = 0; i < fList.getLength(); i++) { |
| Element fieldElement = (Element) fList.item(i); |
| ModelField modelField = createModelField(fieldElement); |
| |
| // if the position is not specified, assume the start position based on last entry |
| if ((i > 0) && (modelField.position == -1)) { |
| modelField.position = priorEnd; |
| } |
| priorEnd = modelField.position + modelField.length; |
| record.fields.add(modelField); |
| } |
| |
| return record; |
| } |
| |
| /** |
| * Creates a Collection with the dataFileName of each DataFile defined in the |
| * specified XML DataFile Descriptor file. |
| * |
| * @return A Collection of dataFileName Strings |
| */ |
| public Collection<String> getDataFileNames() { |
| return this.modelDataFiles.keySet(); |
| } |
| |
| /** |
| * Creates a Iterator with the dataFileName of each DataFile defined in the specified |
| * XML DataFile Descriptor file. |
| * |
| * @return A Iterator of dataFileName Strings |
| */ |
| public Iterator<String> getDataFileNamesIterator() { |
| return this.modelDataFiles.keySet().iterator(); |
| } |
| |
| /** |
| * Gets an DataFile object based on a definition from the specified XML DataFile |
| * descriptor file. |
| * |
| * @param dataFileName |
| * The dataFileName of the DataFile definition to use. |
| * @return An DataFile object describing the specified dataFile of the specified |
| * descriptor file. |
| */ |
| public ModelDataFile getModelDataFile(String dataFileName) { |
| return this.modelDataFiles.get(dataFileName); |
| } |
| |
| public Map<String, ModelDataFile> getModelDataFiles() { |
| return this.modelDataFiles; |
| } |
| } |