mirror of
https://github.com/plexusorg/toml4j.git
synced 2024-12-28 19:24:15 +00:00
Use 'write' rather than 'serialize'.
Also refactor ValueWriter implementations into ValueConverter implementations, where possible.
This commit is contained in:
parent
ca6e043926
commit
c076099ddd
25 changed files with 412 additions and 303 deletions
|
@ -5,7 +5,7 @@ import java.lang.reflect.Array;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
abstract class ArraySerializer implements Serializer {
|
||||
abstract class ArrayValueWriter implements ValueWriter {
|
||||
static protected boolean isArrayish(Object value) {
|
||||
return value instanceof Collection || value.getClass().isArray();
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ abstract class ArraySerializer implements Serializer {
|
|||
static boolean isArrayOfPrimitive(Object array) {
|
||||
Object first = peek(array);
|
||||
if (first != null) {
|
||||
Serializer serializer = Serializers.findSerializerFor(first);
|
||||
return serializer.isPrimitiveType() || isArrayish(first);
|
||||
ValueWriter valueWriter = ValueWriters.findWriterFor(first);
|
||||
return valueWriter.isPrimitiveType() || isArrayish(first);
|
||||
}
|
||||
|
||||
return false;
|
|
@ -3,7 +3,7 @@ package com.moandjiezana.toml;
|
|||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
||||
class BooleanConverter implements ValueConverter {
|
||||
class BooleanConverter implements ValueConverter, ValueWriter {
|
||||
|
||||
static final BooleanConverter BOOLEAN_PARSER = new BooleanConverter();
|
||||
|
||||
|
@ -24,5 +24,25 @@ class BooleanConverter implements ValueConverter {
|
|||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Object value) {
|
||||
return Boolean.class.isInstance(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context) {
|
||||
context.output.append(value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitiveType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private BooleanConverter() {}
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
class BooleanSerializer implements Serializer {
|
||||
static final Serializer BOOLEAN_SERIALIZER = new BooleanSerializer();
|
||||
|
||||
@Override
|
||||
public boolean canSerialize(Object value) {
|
||||
return Boolean.class.isInstance(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Object value, SerializerContext context) {
|
||||
context.serialized.append(value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitiveType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTable() {
|
||||
return false;
|
||||
}
|
||||
}
|
25
src/main/java/com/moandjiezana/toml/BooleanValueWriter.java
Normal file
25
src/main/java/com/moandjiezana/toml/BooleanValueWriter.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
class BooleanValueWriter implements ValueWriter {
|
||||
static final ValueWriter BOOLEAN_VALUE_WRITER = new BooleanValueWriter();
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Object value) {
|
||||
return Boolean.class.isInstance(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context) {
|
||||
context.output.append(value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitiveType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTable() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,14 +1,18 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class DateConverter implements ValueConverter {
|
||||
class DateConverter implements ValueConverter, ValueWriter {
|
||||
|
||||
static final DateConverter DATE_PARSER = new DateConverter();
|
||||
private static final Pattern DATE_REGEX = Pattern.compile("(\\d{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9])(\\.\\d*)?(Z|(?:[+\\-]\\d{2}:\\d{2}))(.*)");
|
||||
private static final Calendar calendar = new GregorianCalendar();
|
||||
|
||||
@Override
|
||||
public boolean canConvert(String s) {
|
||||
|
@ -79,6 +83,29 @@ class DateConverter implements ValueConverter {
|
|||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Object value) {
|
||||
return value instanceof Date;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:m:ss");
|
||||
context.output.append(dateFormat.format(value));
|
||||
int tzOffset = (calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET)) / (60 * 1000);
|
||||
context.output.append(String.format("%+03d:%02d", tzOffset / 60, tzOffset % 60));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitiveType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private DateConverter() {}
|
||||
}
|
||||
|
|
|
@ -5,21 +5,21 @@ import java.util.Calendar;
|
|||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
class DateSerializer implements Serializer {
|
||||
static final Serializer DATE_SERIALIZER = new DateSerializer();
|
||||
class DateValueWriter implements ValueWriter {
|
||||
static final ValueWriter DATE_VALUE_WRITER = new DateValueWriter();
|
||||
private static final Calendar calendar = new GregorianCalendar();
|
||||
|
||||
@Override
|
||||
public boolean canSerialize(Object value) {
|
||||
public boolean canWrite(Object value) {
|
||||
return value instanceof Date;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Object value, SerializerContext context) {
|
||||
public void write(Object value, WriterContext context) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:m:ss");
|
||||
context.serialized.append(dateFormat.format(value));
|
||||
context.output.append(dateFormat.format(value));
|
||||
int tzOffset = (calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET)) / (60 * 1000);
|
||||
context.serialized.append(String.format("%+03d:%02d", tzOffset / 60, tzOffset % 60));
|
||||
context.output.append(String.format("%+03d:%02d", tzOffset / 60, tzOffset % 60));
|
||||
}
|
||||
|
||||
@Override
|
|
@ -4,25 +4,25 @@ import java.util.Map;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.moandjiezana.toml.PrimitiveArraySerializer.PRIMITIVE_ARRAY_SERIALIZER;
|
||||
import static com.moandjiezana.toml.TableArraySerializer.TABLE_ARRAY_SERIALIZER;
|
||||
import static com.moandjiezana.toml.PrimitiveArrayValueWriter.PRIMITIVE_ARRAY_VALUE_WRITER;
|
||||
import static com.moandjiezana.toml.TableArrayValueWriter.TABLE_ARRAY_VALUE_WRITER;
|
||||
|
||||
class MapSerializer implements Serializer {
|
||||
static final Serializer MAP_SERIALIZER = new MapSerializer();
|
||||
class MapValueWriter implements ValueWriter {
|
||||
static final ValueWriter MAP_VALUE_WRITER = new MapValueWriter();
|
||||
|
||||
private static final Pattern requiredQuotingPattern = Pattern.compile("^.*[^A-Za-z\\d_-].*$");
|
||||
|
||||
@Override
|
||||
public boolean canSerialize(Object value) {
|
||||
public boolean canWrite(Object value) {
|
||||
return value instanceof Map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Object value, SerializerContext context) {
|
||||
public void write(Object value, WriterContext context) {
|
||||
Map from = (Map) value;
|
||||
|
||||
if (hasPrimitiveValues(from)) {
|
||||
context.serializeKey();
|
||||
context.writeKey();
|
||||
}
|
||||
|
||||
// Render primitive types and arrays of primitive first so they are
|
||||
|
@ -33,16 +33,16 @@ class MapSerializer implements Serializer {
|
|||
continue;
|
||||
}
|
||||
|
||||
Serializer serializer = Serializers.findSerializerFor(fromValue);
|
||||
if (serializer.isPrimitiveType()) {
|
||||
ValueWriter valueWriter = ValueWriters.findWriterFor(fromValue);
|
||||
if (valueWriter.isPrimitiveType()) {
|
||||
context.indent();
|
||||
context.serialized.append(quoteKey(key)).append(" = ");
|
||||
serializer.serialize(fromValue, context);
|
||||
context.serialized.append('\n');
|
||||
} else if (serializer == PRIMITIVE_ARRAY_SERIALIZER) {
|
||||
context.serialized.append(quoteKey(key)).append(" = ");
|
||||
serializer.serialize(fromValue, context);
|
||||
context.serialized.append('\n');
|
||||
context.output.append(quoteKey(key)).append(" = ");
|
||||
valueWriter.write(fromValue, context);
|
||||
context.output.append('\n');
|
||||
} else if (valueWriter == PRIMITIVE_ARRAY_VALUE_WRITER) {
|
||||
context.output.append(quoteKey(key)).append(" = ");
|
||||
valueWriter.write(fromValue, context);
|
||||
context.output.append('\n');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,9 +53,9 @@ class MapSerializer implements Serializer {
|
|||
continue;
|
||||
}
|
||||
|
||||
Serializer serializer = Serializers.findSerializerFor(fromValue);
|
||||
if (serializer.isTable() || serializer == TABLE_ARRAY_SERIALIZER) {
|
||||
serializer.serialize(fromValue, context.extend(quoteKey(key)));
|
||||
ValueWriter valueWriter = ValueWriters.findWriterFor(fromValue);
|
||||
if (valueWriter.isTable() || valueWriter == TABLE_ARRAY_VALUE_WRITER) {
|
||||
valueWriter.write(fromValue, context.extend(quoteKey(key)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,8 +87,8 @@ class MapSerializer implements Serializer {
|
|||
continue;
|
||||
}
|
||||
|
||||
Serializer serializer = Serializers.findSerializerFor(fromValue);
|
||||
if (serializer.isPrimitiveType() || serializer == PRIMITIVE_ARRAY_SERIALIZER) {
|
||||
ValueWriter valueWriter = ValueWriters.findWriterFor(fromValue);
|
||||
if (valueWriter.isPrimitiveType() || valueWriter == PRIMITIVE_ARRAY_VALUE_WRITER) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package com.moandjiezana.toml;
|
|||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class NumberConverter implements ValueConverter {
|
||||
class NumberConverter implements ValueConverter, ValueWriter {
|
||||
static final NumberConverter NUMBER_PARSER = new NumberConverter();
|
||||
|
||||
@Override
|
||||
|
@ -82,4 +82,25 @@ class NumberConverter implements ValueConverter {
|
|||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Object value) {
|
||||
return Number.class.isInstance(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context) {
|
||||
context.output.append(value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitiveType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
class NumberSerializer implements Serializer {
|
||||
static final Serializer NUMBER_SERIALIZER = new NumberSerializer();
|
||||
|
||||
@Override
|
||||
public boolean canSerialize(Object value) {
|
||||
return Number.class.isInstance(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Object value, SerializerContext context) {
|
||||
context.serialized.append(value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitiveType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTable() {
|
||||
return false;
|
||||
}
|
||||
}
|
25
src/main/java/com/moandjiezana/toml/NumberValueWriter.java
Normal file
25
src/main/java/com/moandjiezana/toml/NumberValueWriter.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
class NumberValueWriter implements ValueWriter {
|
||||
static final ValueWriter NUMBER_VALUE_WRITER = new NumberValueWriter();
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Object value) {
|
||||
return Number.class.isInstance(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context) {
|
||||
context.output.append(value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitiveType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTable() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -4,25 +4,25 @@ import java.lang.reflect.Field;
|
|||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
|
||||
import static com.moandjiezana.toml.MapSerializer.MAP_SERIALIZER;
|
||||
import static com.moandjiezana.toml.MapValueWriter.MAP_VALUE_WRITER;
|
||||
|
||||
class ObjectSerializer implements Serializer {
|
||||
static final Serializer OBJECT_SERIALIZER = new ObjectSerializer();
|
||||
class ObjectValueWriter implements ValueWriter {
|
||||
static final ValueWriter OBJECT_VALUE_WRITER = new ObjectValueWriter();
|
||||
|
||||
@Override
|
||||
public boolean canSerialize(Object value) {
|
||||
public boolean canWrite(Object value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Object value, SerializerContext context) {
|
||||
public void write(Object value, WriterContext context) {
|
||||
Map<String, Object> to = new LinkedHashMap<String, Object>();
|
||||
Set<Field> fields = getFieldsForClass(value.getClass());
|
||||
for (Field field : fields) {
|
||||
to.put(field.getName(), getFieldValue(field, value));
|
||||
}
|
||||
|
||||
MAP_SERIALIZER.serialize(to, context);
|
||||
MAP_VALUE_WRITER.write(to, context);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,28 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
class PrimitiveArraySerializer extends ArraySerializer {
|
||||
static final Serializer PRIMITIVE_ARRAY_SERIALIZER = new PrimitiveArraySerializer();
|
||||
|
||||
@Override
|
||||
public boolean canSerialize(Object value) {
|
||||
return isArrayish(value) && isArrayOfPrimitive(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Object value, SerializerContext context) {
|
||||
Collection values = normalize(value);
|
||||
|
||||
context.serialized.append("[ ");
|
||||
boolean first = true;
|
||||
for (Object elem : values) {
|
||||
if (!first) {
|
||||
context.serialized.append(", ");
|
||||
}
|
||||
Serializers.serialize(elem, context);
|
||||
first = false;
|
||||
}
|
||||
context.serialized.append(" ]");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
class PrimitiveArrayValueWriter extends ArrayValueWriter {
|
||||
static final ValueWriter PRIMITIVE_ARRAY_VALUE_WRITER = new PrimitiveArrayValueWriter();
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Object value) {
|
||||
return isArrayish(value) && isArrayOfPrimitive(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context) {
|
||||
Collection values = normalize(value);
|
||||
|
||||
context.output.append("[ ");
|
||||
boolean first = true;
|
||||
for (Object elem : values) {
|
||||
if (!first) {
|
||||
context.output.append(", ");
|
||||
}
|
||||
ValueWriters.write(elem, context);
|
||||
first = false;
|
||||
}
|
||||
context.output.append(" ]");
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
interface Serializer {
|
||||
boolean canSerialize(Object value);
|
||||
|
||||
void serialize(Object value, SerializerContext context);
|
||||
|
||||
boolean isPrimitiveType();
|
||||
|
||||
boolean isTable();
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
class SerializerContext {
|
||||
private String key = "";
|
||||
private boolean isArrayOfTable = false;
|
||||
StringBuilder serialized = new StringBuilder();
|
||||
|
||||
SerializerContext(String key, StringBuilder serialized) {
|
||||
this.key = key;
|
||||
this.serialized = serialized;
|
||||
}
|
||||
|
||||
SerializerContext() {
|
||||
}
|
||||
|
||||
SerializerContext extend(String newKey) {
|
||||
String fullKey = key + (key.isEmpty() ? newKey : "." + newKey);
|
||||
|
||||
return new SerializerContext(fullKey, serialized);
|
||||
}
|
||||
|
||||
SerializerContext extend() {
|
||||
return new SerializerContext(key, serialized);
|
||||
}
|
||||
|
||||
void serializeKey() {
|
||||
if (key.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (serialized.length() > 0) {
|
||||
serialized.append('\n');
|
||||
}
|
||||
|
||||
if (isArrayOfTable) {
|
||||
serialized.append("[[").append(key).append("]]\n");
|
||||
} else {
|
||||
serialized.append('[').append(key).append("]\n");
|
||||
}
|
||||
}
|
||||
|
||||
void indent() {
|
||||
serialized.append(key.isEmpty() ? "" : " ");
|
||||
}
|
||||
|
||||
SerializerContext setIsArrayOfTable(boolean isArrayOfTable) {
|
||||
this.isArrayOfTable = isArrayOfTable;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static com.moandjiezana.toml.BooleanSerializer.BOOLEAN_SERIALIZER;
|
||||
import static com.moandjiezana.toml.DateSerializer.DATE_SERIALIZER;
|
||||
import static com.moandjiezana.toml.MapSerializer.MAP_SERIALIZER;
|
||||
import static com.moandjiezana.toml.NumberSerializer.NUMBER_SERIALIZER;
|
||||
import static com.moandjiezana.toml.ObjectSerializer.OBJECT_SERIALIZER;
|
||||
import static com.moandjiezana.toml.PrimitiveArraySerializer.PRIMITIVE_ARRAY_SERIALIZER;
|
||||
import static com.moandjiezana.toml.StringSerializer.STRING_SERIALIZER;
|
||||
import static com.moandjiezana.toml.TableArraySerializer.TABLE_ARRAY_SERIALIZER;
|
||||
|
||||
abstract class Serializers {
|
||||
private static final Serializer[] SERIALIZERS = {
|
||||
STRING_SERIALIZER, NUMBER_SERIALIZER, BOOLEAN_SERIALIZER, DATE_SERIALIZER,
|
||||
MAP_SERIALIZER, PRIMITIVE_ARRAY_SERIALIZER, TABLE_ARRAY_SERIALIZER
|
||||
};
|
||||
|
||||
static Serializer findSerializerFor(Object value) {
|
||||
for (Serializer serializer : SERIALIZERS) {
|
||||
if (serializer.canSerialize(value)) {
|
||||
return serializer;
|
||||
}
|
||||
}
|
||||
|
||||
return OBJECT_SERIALIZER;
|
||||
}
|
||||
|
||||
static String serialize(Object value) {
|
||||
SerializerContext context = new SerializerContext();
|
||||
serialize(value, context);
|
||||
|
||||
return context.serialized.toString();
|
||||
}
|
||||
|
||||
static void serialize(Object value, SerializerContext context) {
|
||||
findSerializerFor(value).serialize(value, context);
|
||||
}
|
||||
}
|
|
@ -4,11 +4,23 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class StringConverter implements ValueConverter {
|
||||
class StringConverter implements ValueConverter, ValueWriter {
|
||||
|
||||
static final StringConverter STRING_PARSER = new StringConverter();
|
||||
private static final Pattern UNICODE_REGEX = Pattern.compile("\\\\[uU](.{4})");
|
||||
|
||||
static private final String[] specialCharacterEscapes = new String[93];
|
||||
|
||||
static {
|
||||
specialCharacterEscapes[0x08] = "\\b";
|
||||
specialCharacterEscapes[0x09] = "\\t";
|
||||
specialCharacterEscapes[0x0A] = "\\n";
|
||||
specialCharacterEscapes[0x0C] = "\\f";
|
||||
specialCharacterEscapes[0x0D] = "\\r";
|
||||
specialCharacterEscapes[0x22] = "\\\"";
|
||||
specialCharacterEscapes[0x5C] = "\\";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConvert(String s) {
|
||||
return s.startsWith("\"");
|
||||
|
@ -76,6 +88,45 @@ class StringConverter implements ValueConverter {
|
|||
.replace("\\b", "\b")
|
||||
.replace("\\f", "\f");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Object value) {
|
||||
return value.getClass().isAssignableFrom(String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context) {
|
||||
context.output.append('"');
|
||||
escapeUnicode(value.toString(), context.output);
|
||||
context.output.append('"');
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitiveType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void escapeUnicode(String in, StringBuilder out) {
|
||||
for (int i = 0; i < in.length(); i++) {
|
||||
int codePoint = in.codePointAt(i);
|
||||
if (codePoint < specialCharacterEscapes.length && specialCharacterEscapes[codePoint] != null) {
|
||||
out.append(specialCharacterEscapes[codePoint]);
|
||||
} else if (codePoint > 0x1f && codePoint < 0x7f) {
|
||||
out.append(Character.toChars(codePoint));
|
||||
} else if (codePoint <= 0xFFFF) {
|
||||
out.append(String.format("\\u%04X", codePoint));
|
||||
} else {
|
||||
out.append(String.format("\\U%08X", codePoint));
|
||||
// Skip the low surrogate, which will be the next in the code point sequence.
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private StringConverter() {}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
class StringSerializer implements Serializer {
|
||||
static final Serializer STRING_SERIALIZER = new StringSerializer();
|
||||
class StringValueWriter implements ValueWriter {
|
||||
static final ValueWriter STRING_VALUE_WRITER = new StringValueWriter();
|
||||
|
||||
static private final String[] specialCharacterEscapes = new String[93];
|
||||
|
||||
|
@ -16,15 +16,15 @@ class StringSerializer implements Serializer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canSerialize(Object value) {
|
||||
public boolean canWrite(Object value) {
|
||||
return value.getClass().isAssignableFrom(String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Object value, SerializerContext context) {
|
||||
context.serialized.append('"');
|
||||
escapeUnicode(value.toString(), context.serialized);
|
||||
context.serialized.append('"');
|
||||
public void write(Object value, WriterContext context) {
|
||||
context.output.append('"');
|
||||
escapeUnicode(value.toString(), context.output);
|
||||
context.output.append('"');
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,23 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
class TableArraySerializer extends ArraySerializer {
|
||||
static final Serializer TABLE_ARRAY_SERIALIZER = new TableArraySerializer();
|
||||
|
||||
@Override
|
||||
public boolean canSerialize(Object value) {
|
||||
return isArrayish(value) && !isArrayOfPrimitive(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Object value, SerializerContext context) {
|
||||
Collection values = normalize(value);
|
||||
|
||||
SerializerContext subContext = context.extend().setIsArrayOfTable(true);
|
||||
|
||||
for (Object elem : values) {
|
||||
Serializers.serialize(elem, subContext);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
class TableArrayValueWriter extends ArrayValueWriter {
|
||||
static final ValueWriter TABLE_ARRAY_VALUE_WRITER = new TableArrayValueWriter();
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Object value) {
|
||||
return isArrayish(value) && !isArrayOfPrimitive(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context) {
|
||||
Collection values = normalize(value);
|
||||
|
||||
WriterContext subContext = context.extend().setIsArrayOfTable(true);
|
||||
|
||||
for (Object elem : values) {
|
||||
ValueWriters.write(elem, subContext);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,24 +1,11 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* <p>Provides access to the keys and tables in a TOML data source.</p>
|
||||
*
|
||||
|
@ -378,7 +365,7 @@ public class Toml {
|
|||
* @return a string containing the TOML representation of this Toml instance.
|
||||
*/
|
||||
public String serialize() {
|
||||
return Serializers.serialize(values);
|
||||
return ValueWriters.write(values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -386,13 +373,13 @@ public class Toml {
|
|||
*
|
||||
* The input can comprise arbitrarily nested combinations of Java primitive types,
|
||||
* other {@link Object}s, {@link Map}s, {@link List}s, and Arrays. {@link Object}s and {@link Map}s
|
||||
* are serialized to TOML tables, and {@link List}s and Array to TOML arrays.
|
||||
* are output to TOML tables, and {@link List}s and Array to TOML arrays.
|
||||
*
|
||||
* @param from the object to be serialized
|
||||
* @param from the object to be written
|
||||
* @return a string containing the TOML representation of the given Object
|
||||
*/
|
||||
public static String serializeFrom(Object from) {
|
||||
return Serializers.serialize(from);
|
||||
public static String write(Object from) {
|
||||
return ValueWriters.write(from);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
11
src/main/java/com/moandjiezana/toml/ValueWriter.java
Normal file
11
src/main/java/com/moandjiezana/toml/ValueWriter.java
Normal file
|
@ -0,0 +1,11 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
interface ValueWriter {
|
||||
boolean canWrite(Object value);
|
||||
|
||||
void write(Object value, WriterContext context);
|
||||
|
||||
boolean isPrimitiveType();
|
||||
|
||||
boolean isTable();
|
||||
}
|
41
src/main/java/com/moandjiezana/toml/ValueWriters.java
Normal file
41
src/main/java/com/moandjiezana/toml/ValueWriters.java
Normal file
|
@ -0,0 +1,41 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static com.moandjiezana.toml.BooleanConverter.BOOLEAN_PARSER;
|
||||
import static com.moandjiezana.toml.DateConverter.DATE_PARSER;
|
||||
import static com.moandjiezana.toml.MapValueWriter.MAP_VALUE_WRITER;
|
||||
import static com.moandjiezana.toml.NumberConverter.NUMBER_PARSER;
|
||||
import static com.moandjiezana.toml.ObjectValueWriter.OBJECT_VALUE_WRITER;
|
||||
import static com.moandjiezana.toml.PrimitiveArrayValueWriter.PRIMITIVE_ARRAY_VALUE_WRITER;
|
||||
import static com.moandjiezana.toml.StringConverter.STRING_PARSER;
|
||||
import static com.moandjiezana.toml.TableArrayValueWriter.TABLE_ARRAY_VALUE_WRITER;
|
||||
|
||||
class ValueWriters {
|
||||
|
||||
static ValueWriter findWriterFor(Object value) {
|
||||
for (ValueWriter valueWriter : VALUE_WRITERs) {
|
||||
if (valueWriter.canWrite(value)) {
|
||||
return valueWriter;
|
||||
}
|
||||
}
|
||||
|
||||
return OBJECT_VALUE_WRITER;
|
||||
}
|
||||
|
||||
static String write(Object value) {
|
||||
WriterContext context = new WriterContext();
|
||||
write(value, context);
|
||||
|
||||
return context.output.toString();
|
||||
}
|
||||
|
||||
static void write(Object value, WriterContext context) {
|
||||
findWriterFor(value).write(value, context);
|
||||
}
|
||||
|
||||
private ValueWriters() {}
|
||||
|
||||
private static final ValueWriter[] VALUE_WRITERs = {
|
||||
STRING_PARSER, NUMBER_PARSER, BOOLEAN_PARSER, DATE_PARSER,
|
||||
MAP_VALUE_WRITER, PRIMITIVE_ARRAY_VALUE_WRITER, TABLE_ARRAY_VALUE_WRITER
|
||||
};
|
||||
}
|
50
src/main/java/com/moandjiezana/toml/WriterContext.java
Normal file
50
src/main/java/com/moandjiezana/toml/WriterContext.java
Normal file
|
@ -0,0 +1,50 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
class WriterContext {
|
||||
private String key = "";
|
||||
private boolean isArrayOfTable = false;
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
WriterContext(String key, StringBuilder output) {
|
||||
this.key = key;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
WriterContext() {
|
||||
}
|
||||
|
||||
WriterContext extend(String newKey) {
|
||||
String fullKey = key + (key.isEmpty() ? newKey : "." + newKey);
|
||||
|
||||
return new WriterContext(fullKey, output);
|
||||
}
|
||||
|
||||
WriterContext extend() {
|
||||
return new WriterContext(key, output);
|
||||
}
|
||||
|
||||
void writeKey() {
|
||||
if (key.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (output.length() > 0) {
|
||||
output.append('\n');
|
||||
}
|
||||
|
||||
if (isArrayOfTable) {
|
||||
output.append("[[").append(key).append("]]\n");
|
||||
} else {
|
||||
output.append('[').append(key).append("]\n");
|
||||
}
|
||||
}
|
||||
|
||||
void indent() {
|
||||
output.append(key.isEmpty() ? "" : " ");
|
||||
}
|
||||
|
||||
WriterContext setIsArrayOfTable(boolean isArrayOfTable) {
|
||||
this.isArrayOfTable = isArrayOfTable;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -8,9 +8,9 @@ import java.util.*;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class SerializerTest {
|
||||
public class ValueWriterTest {
|
||||
@Test
|
||||
public void should_serialize_primitive_types() {
|
||||
public void should_write_primitive_types() {
|
||||
class TestClass {
|
||||
public String aString;
|
||||
int anInt;
|
||||
|
@ -31,7 +31,7 @@ public class SerializerTest {
|
|||
o.aDate = new Date();
|
||||
String theDate = formatDate(o.aDate);
|
||||
|
||||
String serialized = Toml.serializeFrom(o);
|
||||
String output = Toml.write(o);
|
||||
String expected = "aString = \"hello\"\n" +
|
||||
"anInt = 4\n" +
|
||||
"aFloat = 1.23\n" +
|
||||
|
@ -39,12 +39,12 @@ public class SerializerTest {
|
|||
"aBoolean = false\n" +
|
||||
"aDate = " + theDate + "\n";
|
||||
|
||||
assertEquals(expected, serialized);
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
private String formatDate(Date date) {
|
||||
// Copying the date formatting code from DateSerializer isn't optimal, but
|
||||
// I can't see any other way to check date serialization - the test gets
|
||||
// Copying the date formatting code from DateValueWriter isn't optimal, but
|
||||
// I can't see any other way to check date formatting - the test gets
|
||||
// run in multiple time zones, so we can't just hard-code a time zone.
|
||||
String dateString = new SimpleDateFormat("yyyy-MM-dd'T'HH:m:ss").format(date);
|
||||
Calendar calendar = new GregorianCalendar();
|
||||
|
@ -55,7 +55,7 @@ public class SerializerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void should_serialize_nested_map() {
|
||||
public void should_write_nested_map() {
|
||||
class SubChild {
|
||||
int anInt;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ public class SerializerTest {
|
|||
parent.child.subChild.anInt = 4;
|
||||
parent.aBoolean = true;
|
||||
|
||||
String serialized = Toml.serializeFrom(parent);
|
||||
String output = Toml.write(parent);
|
||||
String expected = "aBoolean = true\n\n" +
|
||||
"[aMap]\n" +
|
||||
" foo = 1\n" +
|
||||
|
@ -90,23 +90,23 @@ public class SerializerTest {
|
|||
" anInt = 2\n\n" +
|
||||
"[child.subChild]\n" +
|
||||
" anInt = 4\n";
|
||||
assertEquals(expected, serialized);
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_serialize_array_of_primitive() {
|
||||
public void should_write_array_of_primitive() {
|
||||
class ArrayTest {
|
||||
int[] array = {1, 2, 3};
|
||||
}
|
||||
|
||||
ArrayTest arrayTest = new ArrayTest();
|
||||
String serialized = Toml.serializeFrom(arrayTest);
|
||||
String output = Toml.write(arrayTest);
|
||||
String expected = "array = [ 1, 2, 3 ]\n";
|
||||
assertEquals(expected, serialized);
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_serialize_array_of_tables() {
|
||||
public void should_write_array_of_tables() {
|
||||
class Table {
|
||||
int anInt;
|
||||
|
||||
|
@ -120,28 +120,28 @@ public class SerializerTest {
|
|||
Config config = new Config();
|
||||
config.table = new Table[]{new Table(1), new Table(2)};
|
||||
|
||||
String serialized = Toml.serializeFrom(config);
|
||||
String output = Toml.write(config);
|
||||
String expected = "[[table]]\n" +
|
||||
" anInt = 1\n\n" +
|
||||
"[[table]]\n" +
|
||||
" anInt = 2\n";
|
||||
assertEquals(expected, serialized);
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_serialize_array_of_array() {
|
||||
public void should_write_array_of_array() {
|
||||
class ArrayTest {
|
||||
int[][] array = {{1, 2, 3}, {4, 5, 6}};
|
||||
}
|
||||
ArrayTest arrayTest = new ArrayTest();
|
||||
|
||||
String serialized = Toml.serializeFrom(arrayTest);
|
||||
String output = Toml.write(arrayTest);
|
||||
String expected = "array = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]\n";
|
||||
assertEquals(expected, serialized);
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_serialize_list() {
|
||||
public void should_write_list() {
|
||||
class ListTest {
|
||||
List<Integer> aList = new LinkedList<Integer>();
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ public class SerializerTest {
|
|||
o.aList.add(1);
|
||||
o.aList.add(2);
|
||||
|
||||
assertEquals("aList = [ 1, 2 ]\n", Toml.serializeFrom(o));
|
||||
assertEquals("aList = [ 1, 2 ]\n", Toml.write(o));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -158,7 +158,7 @@ public class SerializerTest {
|
|||
List<Integer> aList = new LinkedList<Integer>();
|
||||
Float[] anArray = new Float[0];
|
||||
}
|
||||
assertEquals("", Toml.serializeFrom(new TestClass()));
|
||||
assertEquals("", Toml.write(new TestClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -173,11 +173,11 @@ public class SerializerTest {
|
|||
B b = new B();
|
||||
}
|
||||
|
||||
assertEquals("[b.c]\n anInt = 1\n", Toml.serializeFrom(new A()));
|
||||
assertEquals("[b.c]\n anInt = 1\n", Toml.write(new A()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_serialize_nested_arrays_of_tables() {
|
||||
public void should_write_nested_arrays_of_tables() {
|
||||
class Physical {
|
||||
String color;
|
||||
String shape;
|
||||
|
@ -235,12 +235,12 @@ public class SerializerTest {
|
|||
"\n";
|
||||
|
||||
|
||||
String serialized = Toml.serializeFrom(basket);
|
||||
assertEquals(expected, serialized);
|
||||
String output = Toml.write(basket);
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_serialize_classes_with_inheritance() {
|
||||
public void should_write_classes_with_inheritance() {
|
||||
class Parent {
|
||||
protected int anInt = 2;
|
||||
}
|
||||
|
@ -250,23 +250,23 @@ public class SerializerTest {
|
|||
|
||||
Child child = new Child();
|
||||
String expected = "aBoolean = true\nanInt = 2\n";
|
||||
assertEquals(expected, Toml.serializeFrom(child));
|
||||
assertEquals(expected, Toml.write(child));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_serialize_empty_toml_to_empty_string() {
|
||||
public void should_write_empty_toml_to_empty_string() {
|
||||
Toml toml = new Toml();
|
||||
assertEquals("", toml.serialize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_serialize_strings_to_toml_utf8() throws UnsupportedEncodingException {
|
||||
public void should_write_strings_to_toml_utf8() throws UnsupportedEncodingException {
|
||||
String input = " é foo € \b \t \n \f \r \" \\ ";
|
||||
assertEquals("\" \\u00E9 foo \\u20AC \\b \\t \\n \\f \\r \\\" \\ \"", Toml.serializeFrom(input));
|
||||
assertEquals("\" \\u00E9 foo \\u20AC \\b \\t \\n \\f \\r \\\" \\ \"", Toml.write(input));
|
||||
|
||||
// Check unicode code points greater than 0XFFFF
|
||||
input = " \uD801\uDC28 \uD840\uDC0B ";
|
||||
assertEquals("\" \\U00010428 \\U0002000B \"", Toml.serializeFrom(input));
|
||||
assertEquals("\" \\U00010428 \\U0002000B \"", Toml.write(input));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -281,11 +281,11 @@ public class SerializerTest {
|
|||
"\"5€\" = 2\n" +
|
||||
"\"c$d\" = 3\n" +
|
||||
"\"e/f\" = 4\n";
|
||||
assertEquals(expected, Toml.serializeFrom(aMap));
|
||||
assertEquals(expected, Toml.write(aMap));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_serialize_from_toml() {
|
||||
public void should_write_from_toml() {
|
||||
String tomlString = "a = 1\n";
|
||||
Toml toml = new Toml().parse(tomlString);
|
||||
assertEquals(tomlString, toml.serialize());
|
Loading…
Reference in a new issue