Add writer indentation policy controls.

Set the default indentation to 0.
This commit is contained in:
Jonathan Wood 2015-06-28 10:30:35 -07:00
parent 24a6503d19
commit 72941c146d
7 changed files with 185 additions and 37 deletions

View file

@ -56,7 +56,7 @@ class MapValueWriter implements ValueWriter {
ValueWriter valueWriter = WRITERS.findWriterFor(fromValue); ValueWriter valueWriter = WRITERS.findWriterFor(fromValue);
if (valueWriter.isTable() || valueWriter == TABLE_ARRAY_VALUE_WRITER) { if (valueWriter.isTable() || valueWriter == TABLE_ARRAY_VALUE_WRITER) {
valueWriter.write(fromValue, context.extend(quoteKey(key))); valueWriter.write(fromValue, context.pushTable(quoteKey(key)));
} }
} }
} }

View file

@ -16,7 +16,7 @@ class TableArrayValueWriter extends ArrayValueWriter {
public void write(Object value, WriterContext context) { public void write(Object value, WriterContext context) {
Collection values = normalize(value); Collection values = normalize(value);
WriterContext subContext = context.extend().setIsArrayOfTable(true); WriterContext subContext = context.pushTableFromArray();
for (Object elem : values) { for (Object elem : values) {
WRITERS.write(elem, subContext); WRITERS.write(elem, subContext);

View file

@ -24,6 +24,9 @@ import static com.moandjiezana.toml.ValueWriters.WRITERS;
* </code></pre> * </code></pre>
*/ */
public class TomlWriter { public class TomlWriter {
private WriterIndentationPolicy indentationPolicy = new WriterIndentationPolicy();
/** /**
* Creates a TomlWriter instance. * Creates a TomlWriter instance.
*/ */
@ -36,7 +39,7 @@ public class TomlWriter {
* @return a string containing the TOML representation of the given Object * @return a string containing the TOML representation of the given Object
*/ */
public String write(Object from) { public String write(Object from) {
return WRITERS.write(from); return WRITERS.write(from, this);
} }
/** /**
@ -73,4 +76,21 @@ public class TomlWriter {
writer.write(write(from)); writer.write(write(from));
writer.close(); writer.close();
} }
public WriterIndentationPolicy getIndentationPolicy() {
return indentationPolicy;
}
/**
* Set the {@link WriterIndentationPolicy} for this writer.
*
* If unset, the default policy (no indentation) is used.
*
* @param indentationPolicy the new policy
* @return this TomlWriter instance
*/
public TomlWriter setIndentationPolicy(WriterIndentationPolicy indentationPolicy) {
this.indentationPolicy = indentationPolicy;
return this;
}
} }

View file

@ -23,8 +23,8 @@ class ValueWriters {
return OBJECT_VALUE_WRITER; return OBJECT_VALUE_WRITER;
} }
String write(Object value) { String write(Object value, TomlWriter tomlWriter) {
WriterContext context = new WriterContext(); WriterContext context = new WriterContext(tomlWriter);
write(value, context); write(value, context);
return context.output.toString(); return context.output.toString();

View file

@ -1,26 +1,43 @@
package com.moandjiezana.toml; package com.moandjiezana.toml;
import java.util.Arrays;
class WriterContext { class WriterContext {
private String key = ""; private String key = "";
private String currentTableIndent = "";
private String currentFieldIndent = "";
private boolean isArrayOfTable = false; private boolean isArrayOfTable = false;
private final TomlWriter tomlWriter;
StringBuilder output = new StringBuilder(); StringBuilder output = new StringBuilder();
WriterContext(String key, StringBuilder output) { WriterContext(String key, String tableIndent, StringBuilder output, TomlWriter tomlWriter) {
this.key = key; this.key = key;
this.currentTableIndent = tableIndent;
this.currentFieldIndent = tableIndent + fillStringWithSpaces(tomlWriter.getIndentationPolicy().getKeyValueIndent());
this.output = output; this.output = output;
this.tomlWriter = tomlWriter;
} }
WriterContext() { WriterContext(TomlWriter tomlWriter) {
this.tomlWriter = tomlWriter;
}
WriterContext pushTable(String newKey) {
String newIndent = "";
if (!key.isEmpty()) {
newIndent = growIndent(tomlWriter.getIndentationPolicy());
} }
WriterContext extend(String newKey) {
String fullKey = key + (key.isEmpty() ? newKey : "." + newKey); String fullKey = key + (key.isEmpty() ? newKey : "." + newKey);
return new WriterContext(fullKey, output); return new WriterContext(fullKey, newIndent, output, tomlWriter);
} }
WriterContext extend() { WriterContext pushTableFromArray() {
return new WriterContext(key, output); WriterContext subContext = new WriterContext(key, currentTableIndent, output, tomlWriter);
subContext.setIsArrayOfTable(true);
return subContext;
} }
void writeKey() { void writeKey() {
@ -32,6 +49,8 @@ class WriterContext {
output.append('\n'); output.append('\n');
} }
output.append(currentTableIndent);
if (isArrayOfTable) { if (isArrayOfTable) {
output.append("[[").append(key).append("]]\n"); output.append("[[").append(key).append("]]\n");
} else { } else {
@ -40,11 +59,24 @@ class WriterContext {
} }
void indent() { void indent() {
output.append(key.isEmpty() ? "" : " "); if (!key.isEmpty()) {
output.append(currentFieldIndent);
}
} }
WriterContext setIsArrayOfTable(boolean isArrayOfTable) { WriterContext setIsArrayOfTable(boolean isArrayOfTable) {
this.isArrayOfTable = isArrayOfTable; this.isArrayOfTable = isArrayOfTable;
return this; return this;
} }
private String growIndent(WriterIndentationPolicy indentationPolicy) {
return currentTableIndent + fillStringWithSpaces(indentationPolicy.getTableIndent());
}
private String fillStringWithSpaces(int count) {
char[] chars = new char[count];
Arrays.fill(chars, ' ');
return new String(chars);
}
} }

View file

@ -0,0 +1,41 @@
package com.moandjiezana.toml;
/**
* Controls how a {@link TomlWriter} indents tables and key/value pairs.
*
* The default policy is to not indent.
*/
public class WriterIndentationPolicy {
private int tableIndent = 0;
private int keyValueIndent = 0;
public int getTableIndent() {
return tableIndent;
}
/**
* Sets the number of spaces a nested table name is indented.
*
* @param tableIndent number of spaces to indent
* @return this WriterIndentationPolicy instance
*/
public WriterIndentationPolicy setTableIndent(int tableIndent) {
this.tableIndent = tableIndent;
return this;
}
public int getKeyValueIndent() {
return keyValueIndent;
}
/**
* Sets the number of spaces key/value pairs within a table are indented.
*
* @param keyValueIndent number of spaces to indent
* @return this WriterIndentationPolicy instance
*/
public WriterIndentationPolicy setKeyValueIndent(int keyValueIndent) {
this.keyValueIndent = keyValueIndent;
return this;
}
}

View file

@ -60,8 +60,6 @@ public class ValueWriterTest {
return dateString; return dateString;
} }
@Test
public void should_write_nested_map() {
class SubChild { class SubChild {
int anInt; int anInt;
} }
@ -75,6 +73,7 @@ public class ValueWriterTest {
boolean aBoolean; boolean aBoolean;
} }
private Parent buildNestedMap() {
Parent parent = new Parent(); Parent parent = new Parent();
parent.aMap = new LinkedHashMap<String, Object>(); parent.aMap = new LinkedHashMap<String, Object>();
parent.aMap.put("foo", 1); parent.aMap.put("foo", 1);
@ -86,7 +85,63 @@ public class ValueWriterTest {
parent.child.subChild.anInt = 4; parent.child.subChild.anInt = 4;
parent.aBoolean = true; parent.aBoolean = true;
String output = new TomlWriter().write(parent); return parent;
}
@Test
public void should_write_nested_map() {
String output = new TomlWriter().write(buildNestedMap());
String expected = "aBoolean = true\n\n" +
"[aMap]\n" +
"foo = 1\n" +
"bar = \"value1\"\n" +
"\"baz.x\" = true\n\n" +
"[child]\n" +
"anInt = 2\n\n" +
"[child.subChild]\n" +
"anInt = 4\n";
assertEquals(expected, output);
}
@Test
public void should_follow_indentation_policy_of_indented_values() {
String output = new TomlWriter().
setIndentationPolicy(new WriterIndentationPolicy().setKeyValueIndent(2)).
write(buildNestedMap());
String expected = "aBoolean = true\n\n" +
"[aMap]\n" +
" foo = 1\n" +
" bar = \"value1\"\n" +
" \"baz.x\" = true\n\n" +
"[child]\n" +
" anInt = 2\n\n" +
"[child.subChild]\n" +
" anInt = 4\n";
assertEquals(expected, output);
}
@Test
public void should_follow_indentation_policy_of_indented_tables() {
String output = new TomlWriter().
setIndentationPolicy(new WriterIndentationPolicy().setTableIndent(2)).
write(buildNestedMap());
String expected = "aBoolean = true\n\n" +
"[aMap]\n" +
"foo = 1\n" +
"bar = \"value1\"\n" +
"\"baz.x\" = true\n\n" +
"[child]\n" +
"anInt = 2\n\n" +
" [child.subChild]\n" +
" anInt = 4\n";
assertEquals(expected, output);
}
@Test
public void should_follow_indentation_policy_of_indented_tables_and_values() {
String output = new TomlWriter().
setIndentationPolicy(new WriterIndentationPolicy().setTableIndent(2).setKeyValueIndent(2)).
write(buildNestedMap());
String expected = "aBoolean = true\n\n" + String expected = "aBoolean = true\n\n" +
"[aMap]\n" + "[aMap]\n" +
" foo = 1\n" + " foo = 1\n" +