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
; this is comment franta-hg@95: *random=value outside of any groups franta-hg@95: * franta-hg@95: *[some_section] franta-hg@95: * franta-hg@95: *; simple entry: franta-hg@95: *key=value franta-hg@95: * franta-hg@95: *; entry starting/ending with whitespace franta-hg@95: *white=" spaces everywhere " ; might have comment franta-hg@95: *alternative=' spaces everywhere ' ; same franta-hg@95: * franta-hg@95: *; entries with subkeys: franta-hg@95: *key[subkey_a]=value franta-hg@95: *key[subkey_b]=value franta-hg@95: * franta-hg@95: *# alternative way to comment franta-hg@95: * franta-hg@95: *[another secion] franta-hg@95: *yes=there might be spaces in names franta-hg@95: *because=they are encoded before putting into XML element names franta-hg@95: *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@77: public static final String ROOT_ELEMENT = "ini"; franta-hg@77: private static final Logger log = Logger.getLogger(Reader.class.getName()); franta-hg@77: franta-hg@2: @Override franta-hg@6: public void parse(InputSource input) throws IOException, SAXException { franta-hg@59: outputStart(); franta-hg@77: franta-hg@77: try (BufferedReader br = new BufferedReader(new InputStreamReader(input.getByteStream()))) { franta-hg@78: FileContext fc = new FileContext(contentHandler); franta-hg@77: for (String currentLine = br.readLine(); currentLine != null; currentLine = br.readLine()) { franta-hg@86: fc.lineNumber++; franta-hg@86: boolean lineProcessed = false; franta-hg@77: for (LINE_TYPE lineType : LINE_TYPE.values()) { franta-hg@86: lineProcessed = lineType.processLine(currentLine, fc); franta-hg@77: if (lineProcessed) { franta-hg@77: break; franta-hg@77: } franta-hg@77: } franta-hg@86: if (!lineProcessed) { franta-hg@86: log.log(Level.SEVERE, "Invalid line in INI file: {0}", currentLine); franta-hg@86: } franta-hg@77: } franta-hg@78: fc.outputEndSection(fc.lastSection); franta-hg@78: franta-hg@77: } franta-hg@77: franta-hg@59: outputEnd(); franta-hg@59: } franta-hg@59: franta-hg@59: private void outputStart() throws SAXException { franta-hg@21: contentHandler.startDocument(); franta-hg@76: contentHandler.lineBreak(); franta-hg@77: contentHandler.startElement(null, null, ROOT_ELEMENT, null); franta-hg@75: contentHandler.lineBreak(); franta-hg@59: } franta-hg@59: franta-hg@59: private void outputEnd() throws SAXException { franta-hg@102: contentHandler.endElement(null, null, ROOT_ELEMENT); franta-hg@75: contentHandler.lineBreak(); franta-hg@21: contentHandler.endDocument(); franta-hg@6: } franta-hg@76: franta-hg@77: private static class FileContext { franta-hg@77: franta-hg@77: private final Alt2ContentHandler contentHandler; franta-hg@78: private String lastSection; franta-hg@86: private int lineNumber; franta-hg@77: franta-hg@77: public FileContext(Alt2ContentHandler contentHandler) { franta-hg@77: this.contentHandler = contentHandler; franta-hg@77: } franta-hg@78: franta-hg@78: protected void outputStartSection(String name) throws SAXException { franta-hg@78: contentHandler.indentation(1); franta-hg@78: contentHandler.startElement(null, null, name, null); franta-hg@78: contentHandler.lineBreak(); franta-hg@78: } franta-hg@78: franta-hg@78: protected void outputEndSection(String name) throws SAXException { franta-hg@78: if (name != null) { franta-hg@78: contentHandler.indentation(1); franta-hg@78: contentHandler.endElement(null, null, name); franta-hg@78: contentHandler.lineBreak(); franta-hg@78: } franta-hg@78: } franta-hg@77: } franta-hg@77: franta-hg@89: private static String encodeXmlName(String originalName, int lineNumber) { franta-hg@89: String encodedName = Functions.encodeXmlName(originalName); franta-hg@89: if (!encodedName.equals(originalName)) { franta-hg@89: log.log(Level.FINE, "Line {0}: name „{1} was encoded to „{2}““", new Object[]{lineNumber, originalName, encodedName}); franta-hg@89: } franta-hg@89: return encodedName; franta-hg@89: } franta-hg@89: franta-hg@77: private static class LineContext { franta-hg@77: franta-hg@77: private final Matcher matcher; franta-hg@77: franta-hg@81: public LineContext(Matcher matcher) { franta-hg@77: this.matcher = matcher; franta-hg@77: } franta-hg@77: } franta-hg@77: franta-hg@77: private enum LINE_TYPE { franta-hg@77: franta-hg@86: BLANK_LINE("\\s*") { franta-hg@86: @Override franta-hg@86: public void processLine(LineContext lc, FileContext fc) throws SAXException { franta-hg@86: log.log(Level.FINEST, "Line {0}: skipping blank line", fc.lineNumber); franta-hg@86: } franta-hg@86: }, franta-hg@83: COMMENT("\\s*(;|#)\\s*(?