# HG changeset patch
# User František Kučera <franta-hg@frantovo.cz>
# Date 1409766494 -7200
# Node ID 12b4c1fc57a81d91ad6f7e40b0adb8759f240a9b
# Parent  c11792ae64891a3f5145d2423f84983a3922e042
in-properties: streaming

diff -r c11792ae6489 -r 12b4c1fc57a8 java/alt2xml-in-properties/src/cz/frantovo/alt2xml/in/properties/Reader.java
--- a/java/alt2xml-in-properties/src/cz/frantovo/alt2xml/in/properties/Reader.java	Wed Sep 03 15:50:16 2014 +0200
+++ b/java/alt2xml-in-properties/src/cz/frantovo/alt2xml/in/properties/Reader.java	Wed Sep 03 19:48:14 2014 +0200
@@ -18,9 +18,15 @@
 package cz.frantovo.alt2xml.in.properties;
 
 import cz.frantovo.alt2xml.AbstractAlt2XmlReader;
+import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
 import java.util.Map.Entry;
 import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
@@ -31,36 +37,115 @@
  */
 public class Reader extends AbstractAlt2XmlReader {
 
+	public static final String PROPERTY_BATCH_MODE = constructPropertyName("properties", "batch-mode");
+	private static final Logger log = Logger.getLogger(Reader.class.getName());
+
 	/**
 	 * <p>
-	 * TODO: streaming
-	 * <p>
-	 * <p>
-	 * TODO: same format as Java XML properties</p>
+	 * TODO: same format as Java XML properties
+	 * </p>
 	 * <p>
 	 * TODO: support also nested mode <code>aaa.bbb.ccc=xxx</code> →
 	 * <code>&lt;aaa&gt;&lt;bbb&gt;&lt;ccc&gt;xxx&lt;/ccc&gt;&lt;/bbb&gt;&lt;/aaa&gt;</code></p>
 	 */
 	@Override
 	public void parse(InputSource input) throws IOException, SAXException {
+		if (isInBatchMode()) {
+			log.log(Level.FINE, "Reading in batch mode");
+			parseAsBatch(input);
+		} else {
+			log.log(Level.FINE, "Reading in streaming mode");
+			parseAsStream(input);
+		}
+	}
+
+	private void parseAsBatch(InputSource input) throws IOException, SAXException {
 		Properties loadedData = new Properties();
 		loadedData.load(input.getByteStream());
 
+		outputStart();
+		outputProperties(loadedData);
+		outputEnd();
+	}
+
+	private void parseAsStream(InputSource input) throws IOException, SAXException {
+
+		outputStart();
+
+		try (BufferedReader br = new BufferedReader(new InputStreamReader(input.getByteStream(), StandardCharsets.ISO_8859_1))) {
+			StringBuilder continuingLine = null;
+			Properties loadedData = new Properties();
+			for (String currentLine = br.readLine(); currentLine != null; currentLine = br.readLine()) {
+				if (currentLine.endsWith("\\")) {
+					if (continuingLine == null) {
+						continuingLine = new StringBuilder();
+					}
+					continuingLine.append(currentLine);
+				} else {
+					String wholeLogicalLine = (continuingLine == null) ? currentLine : continuingLine.append("\n").append(currentLine).toString();
+					continuingLine = null;
+
+					loadedData.load(new StringReader(wholeLogicalLine));
+					outputProperties(loadedData);
+					loadedData.clear();
+				}
+			}
+		}
+
+		outputEnd();
+	}
+
+	/**
+	 * Default mode is streaming.
+	 *
+	 * @return false = do streaming | false = parse whole input as one batch and when all parsed,
+	 * flush output
+	 */
+	private boolean isInBatchMode() {
+		return Boolean.parseBoolean(String.valueOf(properties.get(PROPERTY_BATCH_MODE)));
+	}
+
+	private void outputStart() throws SAXException {
 		contentHandler.startDocument();
 		contentHandler.startElement(null, null, "properties", null);
 
+		outputLineBreak();
+	}
+
+	private void outputProperty(String key, String value) throws SAXException {
+		outputIndentation();
+
+		AttributesImpl attributes = new AttributesImpl();
+		attributes.addAttribute(null, "name", "name", "xs:string", key);
+
+		contentHandler.startElement(null, null, "property", attributes);
+		contentHandler.characters(value.toCharArray(), 0, value.length());
+		contentHandler.endElement(null, null, "property");
+
+		outputLineBreak();
+	}
+
+	private void outputProperties(Properties loadedData) throws SAXException {
 		for (Entry<Object, Object> e : loadedData.entrySet()) {
 			String key = (String) e.getKey();
 			String value = (String) e.getValue();
+			outputProperty(key, value);
+		}
+	}
 
-			AttributesImpl attributes = new AttributesImpl();
-			attributes.addAttribute(null, "name", "name", "xs:string", key);
+	private void outputIndentation() throws SAXException {
+		outputText("\t");
+	}
 
-			contentHandler.startElement(null, null, "property", attributes);
-			contentHandler.characters(value.toCharArray(), 0, value.length());
-			contentHandler.endElement(null, null, "property");
-		}
+	private void outputLineBreak() throws SAXException {
+		outputText("\n");
+	}
 
+	private void outputText(String text) throws SAXException {
+		contentHandler.characters(text.toCharArray(), 0, text.length());
+	}
+
+	private void outputEnd() throws SAXException {
 		contentHandler.endElement(null, null, "properties");
 		contentHandler.endDocument();
 	}