protected Property parse(String line, ValueFactories factories, PropertyFactory propFactory) { if (line.length() == 0) return null; // blank line char firstChar = line.charAt(0); if (firstChar == '#') return null; // comment line if (firstChar == ' ') return null; // ignore line Matcher matcher = PROPERTY_PATTERN.matcher(line); if (!matcher.matches()) { // It should be an empty multi-valued property, and the line consists only of the name ... Name name = factories.getNameFactory().create(decoder.decode(line)); return propFactory.create(name); } String nameString = decoder.decode(matcher.group(1)); String typeString = matcher.group(2); String valuesString = matcher.group(4); Name name = factories.getNameFactory().create(nameString); PropertyType type = PropertyType.valueFor(typeString); Pattern pattern = VALUE_PATTERN; ValueFactory<?> valueFactory = factories.getValueFactory(type); boolean binary = false; boolean decode = false; if (type == PropertyType.STRING) { // Parse the double-quoted value(s) ... pattern = STRING_VALUE_PATTERN; decode = true; } else if (type == PropertyType.BINARY) { binary = true; } Matcher valuesMatcher = pattern.matcher(valuesString); List<Object> values = new ArrayList<Object>(); while (valuesMatcher.find()) { String valueString = valuesMatcher.group(1); if (binary) { // The value is a hexadecimal-encoded byte array ... byte[] binaryValue = StringUtil.fromHexString(valueString); Object value = valueFactory.create(binaryValue); values.add(value); } else { if (decode) valueString = quoter.decode(valueString); Object value = valueFactory.create(valueString); values.add(value); } } if (values.isEmpty()) return null; return propFactory.create(name, type, values); }