ArrayList<String> processLines(final String filename, ArrayList<String> lines) {
		Collections.sort(lines, KEY_COMPARATOR);
		ArrayList<String> result = new ArrayList<String>(lines.size());
		String lastKey = null;
		String lastValue = null;
		for (final String line : lines) {
			if (line.indexOf('#') == 0 || line.matches("\\s*"))
				continue;
			final String standardUnicodeLine = convertUnicodeCharacterRepresentation(line);
			final String[] keyValue = standardUnicodeLine.split("\\s*=\\s*", 2);
			if (keyValue.length != 2 || keyValue[0].length() == 0) {
				// broken line: no '=' sign or empty key (we had " = ======")
				warn(filename + ": no key/val: " + line);
				continue;
			}
			final String thisKey = keyValue[0];
			String thisValue = keyValue[1].trim();
			if (thisValue.matches("(\\[auto\\]|\\[translate me\\])?")) {
				warn(filename + ": drop empty translation: " + line);
				continue;
			}
			if (thisValue.indexOf("{1}") != -1 && keyValue[1].indexOf("{0}") == -1) {
				warn(filename + ": errorneous placeholders usage: {1} used without {0}: " + line);
			}
			if (thisValue.matches(".*\\$\\d.*")) {
				warn(filename + ": use '{0}' instead of '$1' as placeholder! (likewise for $2...): " + line);
				thisValue = thisValue.replaceAll("\\$1", "{0}").replaceAll("\\$2", "{1}");
			}
			if (thisValue.matches(".*\\{\\d[^},]*")) {
				warn(filename + ": mismatched braces in placeholder: '{' not closed by '}': " + line);
			}
			if (lastKey != null && thisKey.equals(lastKey)) {
				if (quality(thisValue) < quality(lastValue)) {
					log(filename + ": drop " + TaskUtils.toLine(lastKey, thisValue));
					continue;
				}
				else if (quality(thisValue) == quality(lastValue)) {
					if (thisValue.equals(lastValue)) {
						log(filename + ": drop duplicate " + TaskUtils.toLine(lastKey, thisValue));
					}
					else if (quality(thisValue) == QUALITY_MANUALLY_TRANSLATED) {
						warn(filename //
						        + ": drop one of two of equal quality (revisit!):keep: "
						        + TaskUtils.toLine(lastKey, lastValue));
						warn(filename //
						        + ": drop one of two of equal quality (revisit!):drop: "
						        + TaskUtils.toLine(thisKey, thisValue));
					}
					else {
						log(filename + ": drop " + TaskUtils.toLine(lastKey, thisValue));
					}
					continue;
				}
				else {
					log(filename + ": drop " + TaskUtils.toLine(lastKey, lastValue));
				}
				lastValue = thisValue;
			}
			else {
				if (lastKey != null)
					result.add(TaskUtils.toLine(lastKey, lastValue));
				lastKey = thisKey;
				lastValue = thisValue;
			}
		}
		if (lastKey != null)
			result.add(TaskUtils.toLine(lastKey, lastValue));
		return result;
	}
@Test
	public void testRemoveEmptyLines() throws Exception {
		final String msgConserved = "empty lines should be conserved";
		final String msgRemoved = "empty lines should be removed";
		final FormatTranslation formatTranslation = new FormatTranslation();
		String input;
		ArrayList<String> lines = new ArrayList<String>();
		//
		input = "\n \nx=y\n\n";
		assertTrue("unique unix", TaskUtils.checkEolStyleAndReadLines(input, lines, unix));
		assertEquals(msgConserved, 4, lines.size());
		assertEquals(msgRemoved, 1, formatTranslation.processLines("a_file", new ArrayList<String>(lines)).size());
		//
		input = "\n";
		assertTrue("unique unix", TaskUtils.checkEolStyleAndReadLines(input, lines, unix));
		assertEquals(msgConserved, 1, lines.size());
		assertEquals(msgRemoved, 0, formatTranslation.processLines("a_file", new ArrayList<String>(lines)).size());
		//
		input = "  \n";
		assertTrue("unique unix", TaskUtils.checkEolStyleAndReadLines(input, lines, unix));
		assertEquals(msgConserved, 1, lines.size());
		assertEquals(msgRemoved, 0, formatTranslation.processLines("a_file", new ArrayList<String>(lines)).size());
		//
		input = "x=y";
		assertTrue("unique unix", TaskUtils.checkEolStyleAndReadLines(input, lines, unix));
		assertEquals(msgConserved, 1, lines.size());
		assertEquals(msgRemoved, 1, formatTranslation.processLines("a_file", new ArrayList<String>(lines)).size());
		//
	}