franta-hg@11: /** franta-hg@11: * Alt2XML franta-hg@11: * Copyright © 2014 František Kučera (frantovo.cz) franta-hg@11: * franta-hg@11: * This program is free software: you can redistribute it and/or modify franta-hg@11: * it under the terms of the GNU General Public License as published by franta-hg@111: * the Free Software Foundation, version 3 of the License. franta-hg@11: * franta-hg@11: * This program is distributed in the hope that it will be useful, franta-hg@11: * but WITHOUT ANY WARRANTY; without even the implied warranty of franta-hg@11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the franta-hg@11: * GNU General Public License for more details. franta-hg@11: * franta-hg@11: * You should have received a copy of the GNU General Public License franta-hg@11: * along with this program. If not, see . franta-hg@11: */ franta-hg@18: package cz.frantovo.alt2xml.in.properties; franta-hg@2: franta-hg@17: import cz.frantovo.alt2xml.AbstractAlt2XmlReader; franta-hg@59: import java.io.BufferedReader; franta-hg@2: import java.io.IOException; franta-hg@59: import java.io.InputStreamReader; franta-hg@59: import java.io.StringReader; franta-hg@59: import java.nio.charset.StandardCharsets; franta-hg@21: import java.util.Map.Entry; franta-hg@21: import java.util.Properties; franta-hg@59: import java.util.logging.Level; franta-hg@59: import java.util.logging.Logger; franta-hg@2: import org.xml.sax.InputSource; franta-hg@2: import org.xml.sax.SAXException; franta-hg@21: import org.xml.sax.helpers.AttributesImpl; franta-hg@2: franta-hg@2: /** franta-hg@2: * franta-hg@17: * @author Ing. František Kučera (frantovo.cz) franta-hg@2: */ franta-hg@17: public class Reader extends AbstractAlt2XmlReader { franta-hg@13: franta-hg@59: public static final String PROPERTY_BATCH_MODE = constructPropertyName("properties", "batch-mode"); franta-hg@59: private static final Logger log = Logger.getLogger(Reader.class.getName()); franta-hg@59: franta-hg@21: /** franta-hg@21: *

franta-hg@59: * TODO: same format as Java XML properties franta-hg@59: *

franta-hg@21: *

franta-hg@21: * TODO: support also nested mode aaa.bbb.ccc=xxx → franta-hg@21: * <aaa><bbb><ccc>xxx</ccc></bbb></aaa>

franta-hg@21: */ franta-hg@2: @Override franta-hg@6: public void parse(InputSource input) throws IOException, SAXException { franta-hg@59: if (isInBatchMode()) { franta-hg@59: log.log(Level.FINE, "Reading in batch mode"); franta-hg@59: parseAsBatch(input); franta-hg@59: } else { franta-hg@59: log.log(Level.FINE, "Reading in streaming mode"); franta-hg@59: parseAsStream(input); franta-hg@59: } franta-hg@59: } franta-hg@59: franta-hg@59: private void parseAsBatch(InputSource input) throws IOException, SAXException { franta-hg@21: Properties loadedData = new Properties(); franta-hg@21: loadedData.load(input.getByteStream()); franta-hg@6: franta-hg@59: outputStart(); franta-hg@59: outputProperties(loadedData); franta-hg@59: outputEnd(); franta-hg@59: } franta-hg@59: franta-hg@59: private void parseAsStream(InputSource input) throws IOException, SAXException { franta-hg@59: franta-hg@59: outputStart(); franta-hg@59: franta-hg@59: try (BufferedReader br = new BufferedReader(new InputStreamReader(input.getByteStream(), StandardCharsets.ISO_8859_1))) { franta-hg@59: StringBuilder continuingLine = null; franta-hg@59: Properties loadedData = new Properties(); franta-hg@59: for (String currentLine = br.readLine(); currentLine != null; currentLine = br.readLine()) { franta-hg@59: if (currentLine.endsWith("\\")) { franta-hg@59: if (continuingLine == null) { franta-hg@59: continuingLine = new StringBuilder(); franta-hg@59: } franta-hg@59: continuingLine.append(currentLine); franta-hg@59: } else { franta-hg@59: String wholeLogicalLine = (continuingLine == null) ? currentLine : continuingLine.append("\n").append(currentLine).toString(); franta-hg@59: continuingLine = null; franta-hg@59: franta-hg@59: loadedData.load(new StringReader(wholeLogicalLine)); franta-hg@59: outputProperties(loadedData); franta-hg@59: loadedData.clear(); franta-hg@59: } franta-hg@59: } franta-hg@59: } franta-hg@59: franta-hg@59: outputEnd(); franta-hg@59: } franta-hg@59: franta-hg@59: /** franta-hg@59: * Default mode is streaming. franta-hg@59: * franta-hg@107: * @return false = do streaming | true = parse whole input as one batch and when all parsed, franta-hg@59: * flush output franta-hg@59: */ franta-hg@59: private boolean isInBatchMode() { franta-hg@59: return Boolean.parseBoolean(String.valueOf(properties.get(PROPERTY_BATCH_MODE))); franta-hg@59: } franta-hg@59: franta-hg@59: private void outputStart() throws SAXException { franta-hg@21: contentHandler.startDocument(); franta-hg@21: contentHandler.startElement(null, null, "properties", null); franta-hg@21: franta-hg@75: contentHandler.lineBreak(); franta-hg@59: } franta-hg@59: franta-hg@59: private void outputProperty(String key, String value) throws SAXException { franta-hg@75: contentHandler.indentation(1); franta-hg@59: franta-hg@59: AttributesImpl attributes = new AttributesImpl(); franta-hg@59: attributes.addAttribute(null, "name", "name", "xs:string", key); franta-hg@59: franta-hg@59: contentHandler.startElement(null, null, "property", attributes); franta-hg@59: contentHandler.characters(value.toCharArray(), 0, value.length()); franta-hg@59: contentHandler.endElement(null, null, "property"); franta-hg@59: franta-hg@75: contentHandler.lineBreak(); franta-hg@59: } franta-hg@59: franta-hg@59: private void outputProperties(Properties loadedData) throws SAXException { franta-hg@21: for (Entry e : loadedData.entrySet()) { franta-hg@21: String key = (String) e.getKey(); franta-hg@21: String value = (String) e.getValue(); franta-hg@59: outputProperty(key, value); franta-hg@59: } franta-hg@59: } franta-hg@21: franta-hg@59: private void outputEnd() throws SAXException { franta-hg@21: contentHandler.endElement(null, null, "properties"); franta-hg@75: contentHandler.lineBreak(); franta-hg@21: contentHandler.endDocument(); franta-hg@6: } franta-hg@2: }