/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Whole Platform is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ package org.whole.lang.properties.parsers; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.whole.lang.parsers.DefaultDataTypePersistenceParser; import org.whole.lang.properties.reflect.PropertiesEntityDescriptorEnum; import org.whole.lang.reflect.EntityDescriptor; import org.whole.lang.util.StringUtils; /** * @author Enrico Persiani */ public class PropertiesDataTypePersistenceParser extends DefaultDataTypePersistenceParser { private static final Pattern WS_SEQUENCE = Pattern.compile("[ \\t\\f]*[\\r\\n][ \\t\\f\\r\\n]*"); private static class SingletonHolder { private static final PropertiesDataTypePersistenceParser instance = new PropertiesDataTypePersistenceParser(); } public static PropertiesDataTypePersistenceParser instance() { return SingletonHolder.instance; } protected PropertiesDataTypePersistenceParser() { } @Override public String parseString(EntityDescriptor<?> ed, String value) { String stringValue = null; switch (ed.getOrdinal()) { case PropertiesEntityDescriptorEnum.PropertyName_ord: stringValue = parseStringValue(value); break; } if (stringValue != null) return stringValue; else return super.parseString(ed, value); } @Override public String unparseString(EntityDescriptor<?> ed, String value) { switch (ed.getOrdinal()) { case PropertiesEntityDescriptorEnum.PropertyName_ord: return unparseStringValue(value); default: return super.unparseString(ed, value); } } protected String parseStringValue(String value) { return unescapePropertyString(value); } protected String unparseStringValue(String value) { return escapePropertyString(value); } public static String escapePropertyString(String t) { StringBuilder r = new StringBuilder(); for (int j=0; j<t.length(); ++j) { char c = t.charAt(j); if (c==' ') r.append(' '); else if (c=='\n') r.append("\\n"); else if (c=='\r') r.append("\\r"); else if (c=='=') r.append("\\="); else if (c==':') r.append("\\:"); else if (c=='\t') r.append("\\t"); else if (c=='\f') r.append("\\f"); else if (c=='\\') r.append("\\\\"); else if (Character.isISOControl(c) || Character.isWhitespace(c)) { r.append("\\u"); r.append(StringUtils.charToHex(c)); } else r.append(c); } return r.toString(); } /** * Properties escape sequences are specified in * {@link java.util.Properties#load(java.io.Reader) load(Reader)}. */ public static String unescapePropertyString(String t) { StringBuilder r = new StringBuilder(); int length = t.length(); int j=0; while (j<length) { char c = t.charAt(j); if (c=='\\') { c = t.charAt(++j); switch (c) { case 'n': r.append('\n'); break; case 't': r.append('\t'); break; case 'r': r.append('\r'); break; case 'f': r.append('\f'); break; case '\\': r.append('\\'); break; case 'u': r.append((char) Integer.parseInt(t.substring(j+1, j+5), 16)); j += 4; break; case '\t': case '\f': case ' ': Matcher matcher = WS_SEQUENCE.matcher(t.substring(j+1)); if (matcher.find()) { j += matcher.end()-matcher.start(); break; } default: r.append(c); } } else r.append(c); j++; } return r.toString(); } }