/******************************************************************************* * 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.apache.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.apache.ofbiz.base.util.Debug; import org.apache.ofbiz.base.util.UtilValidate; import org.apache.ofbiz.base.util.UtilXml; import org.apache.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; } }