java/alt2xml-in-ini/src/cz/frantovo/alt2xml/in/ini/Reader.java
author František Kučera <franta-hg@frantovo.cz>
Sat, 06 Sep 2014 19:10:52 +0200
changeset 81 a4335757acf1
parent 80 c5816dd82cbb
child 82 547f1246fe35
permissions -rw-r--r--
in-ini: quoted/apostrophed values → include spaces (unquoted → strip spaces)
     1 /**
     2  * Alt2XML
     3  * Copyright © 2014 František Kučera (frantovo.cz)
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, either version 3 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * This program is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License
    16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    17  */
    18 package cz.frantovo.alt2xml.in.ini;
    19 
    20 import cz.frantovo.alt2xml.AbstractAlt2XmlReader;
    21 import cz.frantovo.alt2xml.in.Alt2ContentHandler;
    22 import java.io.BufferedReader;
    23 import java.io.IOException;
    24 import java.io.InputStreamReader;
    25 import java.util.ArrayList;
    26 import java.util.List;
    27 import java.util.logging.Level;
    28 import java.util.logging.Logger;
    29 import java.util.regex.Matcher;
    30 import java.util.regex.Pattern;
    31 import org.xml.sax.InputSource;
    32 import org.xml.sax.SAXException;
    33 
    34 /**
    35  *
    36  * @author Ing. František Kučera (frantovo.cz)
    37  */
    38 public class Reader extends AbstractAlt2XmlReader {
    39 
    40 	public static final String ROOT_ELEMENT = "ini";
    41 	private static final Logger log = Logger.getLogger(Reader.class.getName());
    42 
    43 	@Override
    44 	public void parse(InputSource input) throws IOException, SAXException {
    45 		outputStart();
    46 
    47 		try (BufferedReader br = new BufferedReader(new InputStreamReader(input.getByteStream()))) {
    48 			FileContext fc = new FileContext(contentHandler);
    49 			for (String currentLine = br.readLine(); currentLine != null; currentLine = br.readLine()) {
    50 				for (LINE_TYPE lineType : LINE_TYPE.values()) {
    51 					boolean lineProcessed = lineType.processLine(currentLine, fc);
    52 					if (lineProcessed) {
    53 						break;
    54 					}
    55 				}
    56 			}
    57 			fc.outputEndSection(fc.lastSection);
    58 
    59 		}
    60 
    61 		outputEnd();
    62 	}
    63 
    64 	private void outputStart() throws SAXException {
    65 		contentHandler.startDocument();
    66 		contentHandler.lineBreak();
    67 		contentHandler.startElement(null, null, ROOT_ELEMENT, null);
    68 		contentHandler.lineBreak();
    69 	}
    70 
    71 	private void outputEnd() throws SAXException {
    72 		contentHandler.endElement(null, null, "ini");
    73 		contentHandler.lineBreak();
    74 		contentHandler.endDocument();
    75 	}
    76 
    77 	private static class FileContext {
    78 
    79 		private final Alt2ContentHandler contentHandler;
    80 		private String lastSection;
    81 
    82 		public FileContext(Alt2ContentHandler contentHandler) {
    83 			this.contentHandler = contentHandler;
    84 		}
    85 
    86 		protected void outputStartSection(String name) throws SAXException {
    87 			contentHandler.indentation(1);
    88 			contentHandler.startElement(null, null, name, null);
    89 			contentHandler.lineBreak();
    90 		}
    91 
    92 		protected void outputEndSection(String name) throws SAXException {
    93 			if (name != null) {
    94 				contentHandler.indentation(1);
    95 				contentHandler.endElement(null, null, name);
    96 				contentHandler.lineBreak();
    97 			}
    98 		}
    99 	}
   100 
   101 	private static class LineContext {
   102 
   103 		private final Matcher matcher;
   104 
   105 		public LineContext(Matcher matcher) {
   106 			this.matcher = matcher;
   107 		}
   108 	}
   109 
   110 	private enum LINE_TYPE {
   111 
   112 		COMMENT("\\s*(;|#)\\s*(.*)") {
   113 					@Override
   114 					public void processLine(LineContext lc, FileContext fc) throws SAXException {
   115 						log.log(Level.FINER, "Comment: {0}", lc.matcher.group(2));
   116 					}
   117 
   118 				},
   119 		SECTION("\\s*\\[\\s*([^\\s\\]]+)\\s*\\]\\s*") {
   120 					@Override
   121 					public void processLine(LineContext lc, FileContext fc) throws SAXException {
   122 						String name = lc.matcher.group(1);
   123 						fc.outputEndSection(fc.lastSection);
   124 						fc.outputStartSection(name);
   125 						fc.lastSection = name;
   126 					}
   127 
   128 				},
   129 		ENTRY(
   130 				"\\s*([^=\\s]+)\\s*=\\s*\"([^\"]+)\"", // quoted value → include spaces
   131 				"\\s*([^=\\s]+)\\s*=\\s*'([^']+)'", // apostrophed value → include spaces
   132 				"\\s*([^=\\s]+)\\s*=\\s*(.+)" // unquoted value → strip spaces
   133 		) {
   134 					@Override
   135 					public void processLine(LineContext lc, FileContext fc) throws SAXException {
   136 						String key = lc.matcher.group(1);
   137 						String value = lc.matcher.group(2);
   138 
   139 						fc.contentHandler.indentation(2);
   140 						fc.contentHandler.textElement(value, null, null, key, null);
   141 						fc.contentHandler.lineBreak();
   142 
   143 					}
   144 
   145 				},;
   146 
   147 		private LINE_TYPE(String... patterns) {
   148 			for (String pattern : patterns) {
   149 				this.patterns.add(Pattern.compile(pattern));
   150 			}
   151 		}
   152 
   153 		private final List<Pattern> patterns = new ArrayList<>();
   154 
   155 		protected boolean processLine(String currentLine, FileContext fileContext) throws SAXException {
   156 			for (Pattern pattern : patterns) {
   157 				Matcher m = pattern.matcher(currentLine);
   158 				if (m.matches()) {
   159 					processLine(new LineContext(m), fileContext);
   160 					return true;
   161 				}
   162 			}
   163 			return false;
   164 		}
   165 
   166 		public abstract void processLine(LineContext lc, FileContext fc) throws SAXException;
   167 	}
   168 
   169 }