package org.togglz.core.repository.util;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
/**
* This converter is able to convert string maps to simple strings and vice versa.
*
* @author Christian Kaltepoth
*/
public class DefaultMapSerializer implements MapSerializer {
private final boolean multiline;
private final String lineSeparator;
/**
* Use {@link #create()}
*/
private DefaultMapSerializer(boolean multiline) {
this(multiline, "\n");
}
/**
* Use {@link #create()}
*/
private DefaultMapSerializer(boolean multiline, String lineSeparator) {
this.multiline = multiline;
this.lineSeparator = lineSeparator;
}
/**
* Creates a new instance of the {@link DefaultMapSerializer}.
*/
public static DefaultMapSerializer singleline() {
return new DefaultMapSerializer(false);
}
/**
* Creates a new instance of the {@link DefaultMapSerializer}.
*/
public static DefaultMapSerializer multiline() {
return new DefaultMapSerializer(true);
}
/**
* Creates a new instance of the {@link DefaultMapSerializer}.
*/
public static DefaultMapSerializer multiline(String lineSeparator) {
return new DefaultMapSerializer(true, lineSeparator);
}
/*
* (non-Javadoc)
*
* @see org.togglz.core.util.MapSerializer#convertToString(java.util.Map)
*/
@Override
public String serialize(Map<String, String> map) {
try {
// the format is based on the properties output format
Properties props = new Properties();
props.putAll(map);
Writer writer = new StringWriter();
props.store(writer, null);
// we need a list of strings so we can further process the format
List<String> lines = new ArrayList<String>();
for (String line : writer.toString().split("\r?\n")) {
// comments and empty lines are skipped
if (!line.trim().isEmpty() && !line.trim().startsWith("#")) {
lines.add(line.trim());
}
}
// sort by key so create a canonical format
Collections.sort(lines);
// build the output string
StringBuilder builder = new StringBuilder();
for (String line : lines) {
if (multiline) {
if (builder.length() > 0) {
builder.append(lineSeparator);
}
builder.append(line);
}
else {
if (builder.length() > 0) {
builder.append("&");
}
builder.append(line.replace("&", "\\u0026"));
}
}
return builder.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
/*
* (non-Javadoc)
*
* @see org.togglz.core.util.MapSerializer#convertFromString(java.lang.String)
*/
@Override
public Map<String, String> deserialize(String s) {
try {
String input = multiline ? s : s.replace('&', '\n');
Properties props = new Properties();
if (s != null) {
props.load(new StringReader(input));
}
LinkedHashMap<String, String> result = new LinkedHashMap<String, String>();
for (Entry<Object, Object> entry : props.entrySet()) {
result.put(entry.getKey().toString(), entry.getValue().toString());
}
return result;
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
}