diff --git a/pom.xml b/pom.xml
index 48e3855..7cb0187 100644
--- a/pom.xml
+++ b/pom.xml
@@ -47,6 +47,12 @@
1.4.1
test
+
+ org.hamcrest
+ hamcrest-library
+ 1.3
+ test
+
diff --git a/src/main/java/com/moandjiezana/toml/Toml.java b/src/main/java/com/moandjiezana/toml/Toml.java
index 9d0d7da..5a96182 100644
--- a/src/main/java/com/moandjiezana/toml/Toml.java
+++ b/src/main/java/com/moandjiezana/toml/Toml.java
@@ -18,6 +18,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.parboiled.Parboiled;
import org.parboiled.parserunners.RecoveringParseRunner;
@@ -44,21 +46,23 @@ import com.google.gson.Gson;
*/
public class Toml {
+ private static Pattern ARRAY_INDEX_PATTERN = Pattern.compile("(.*)\\[(\\d+)\\]");
private Map values = new HashMap();
private final Toml defaults;
+ private final Gson gson = new Gson();
/**
* Creates Toml instance with no defaults.
*/
public Toml() {
- this((Toml) null);
+ this(null);
}
/**
* @param defaults fallback values used when the requested key or table is not present.
*/
public Toml(Toml defaults) {
- this.defaults = defaults;
+ this(defaults, new HashMap());
}
/**
@@ -177,7 +181,7 @@ public class Toml {
*/
@SuppressWarnings("unchecked")
public Toml getTable(String key) {
- return new Toml((Map) get(key));
+ return new Toml(null, (Map) get(key));
}
/**
@@ -193,8 +197,9 @@ public class Toml {
}
ArrayList tables = new ArrayList();
+
for (Map table : tableArray) {
- tables.add(new Toml(table));
+ tables.add(new Toml(null, table));
}
return tables;
@@ -219,6 +224,7 @@ public class Toml {
*/
public T to(Class targetClass) {
HashMap valuesCopy = new HashMap(values);
+
if (defaults != null) {
for (Map.Entry entry : defaults.values.entrySet()) {
if (!valuesCopy.containsKey(entry.getKey())) {
@@ -226,7 +232,7 @@ public class Toml {
}
}
}
- Gson gson = new Gson();
+
String json = gson.toJson(valuesCopy);
return gson.fromJson(json, targetClass);
}
@@ -235,32 +241,32 @@ public class Toml {
private Object get(String key) {
String[] split = key.split("\\.");
Object current = new HashMap(values);
- Object currentDefaults = defaults != null ? defaults.values : null;
+
for (String splitKey : split) {
+ Matcher matcher = ARRAY_INDEX_PATTERN.matcher(splitKey);
+ int index = -1;
+
+ if (matcher.find()) {
+ splitKey = matcher.group(1);
+ index = Integer.parseInt(matcher.group(2), 10);
+ }
+
current = ((Map) current).get(splitKey);
- if (currentDefaults != null) {
- currentDefaults = ((Map) currentDefaults).get(splitKey);
- if (current instanceof Map && currentDefaults instanceof Map) {
- for (Map.Entry entry : ((Map) currentDefaults).entrySet()) {
- if (!((Map) current).containsKey(entry.getKey())) {
- ((Map) current).put(entry.getKey(), entry.getValue());
- }
- }
- }
- }
- if (current == null && currentDefaults != null) {
- current = currentDefaults;
+
+ if (index > -1 && current != null) {
+ current = ((List>) current).get(index);
}
+
if (current == null) {
- return null;
+ return defaults != null ? defaults.get(key) : null;
}
}
return current;
}
- private Toml(Map values) {
+ private Toml(Toml defaults, Map values) {
this.values = values != null ? values : Collections.emptyMap();
- this.defaults = null;
+ this.defaults = defaults;
}
}
diff --git a/src/test/java/com/moandjiezana/toml/TableArrayTest.java b/src/test/java/com/moandjiezana/toml/TableArrayTest.java
index ca8b982..095e17c 100644
--- a/src/test/java/com/moandjiezana/toml/TableArrayTest.java
+++ b/src/test/java/com/moandjiezana/toml/TableArrayTest.java
@@ -13,7 +13,7 @@ public class TableArrayTest {
@Test
public void should_parse_table_array() throws Exception {
- Toml toml = new Toml().parse(new File(getClass().getResource("products_table_array.toml").getFile()));
+ Toml toml = new Toml().parse(file("products_table_array"));
List products = toml.getTables("products");
@@ -32,7 +32,7 @@ public class TableArrayTest {
@Test
public void should_parse_nested_table_arrays() throws Exception {
- Toml toml = new Toml().parse(new File(getClass().getResource("fruit_table_array.toml").getFile()));
+ Toml toml = new Toml().parse(file("fruit_table_array"));
List fruits = toml.getTables("fruit");
@@ -56,4 +56,23 @@ public class TableArrayTest {
assertEquals(3, toml.getTable("a").getTable("b").getTables("c").get(0).getLong("id").intValue());
}
+
+ @Test
+ public void should_navigate_array_with_compound_key() throws Exception {
+ Toml toml = new Toml().parse(file("fruit_table_array"));
+
+ List appleVarieties = toml.getTables("fruit[0].variety");
+ Toml appleVariety = toml.getTable("fruit[0].variety[1]");
+ String bananaVariety = toml.getString("fruit[1].variety[0].name");
+
+ assertEquals(2, appleVarieties.size());
+ assertEquals("red delicious", appleVarieties.get(0).getString("name"));
+ assertEquals("granny smith", appleVariety.getString("name"));
+ assertEquals("plantain", bananaVariety);
+ }
+
+ private File file(String fileName) {
+ return new File(getClass().getResource(fileName + ".toml").getFile());
+ }
+
}
diff --git a/src/test/java/com/moandjiezana/toml/TomlDefaultsTest.java b/src/test/java/com/moandjiezana/toml/TomlDefaultsTest.java
index 9acf2a6..cc20819 100644
--- a/src/test/java/com/moandjiezana/toml/TomlDefaultsTest.java
+++ b/src/test/java/com/moandjiezana/toml/TomlDefaultsTest.java
@@ -1,8 +1,11 @@
package com.moandjiezana.toml;
+import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
@@ -13,7 +16,7 @@ public class TomlDefaultsTest {
@Before
public void before() {
- defaultToml = new Toml().parse("a = \"a\"\n[group]\na=\"a\"");
+ defaultToml = new Toml().parse("a = \"a\"\n [group]\n a=\"a\"\n [[array]]\n b=1 [[array]]\n b=2");
}
@Test
@@ -52,10 +55,22 @@ public class TomlDefaultsTest {
}
@Test
- public void should_fall_back_to_key_within_table() throws Exception {
- Toml toml = new Toml(defaultToml).parse("[group]\nb=1");
+ public void should_fall_back_to_table_array() throws Exception {
+ Toml toml = new Toml(defaultToml).parse("");
+
+ assertThat(toml.getTables("array"), hasSize(2));
+ assertThat(toml.getLong("array[1].b"), Matchers.equalTo(2L));
+ }
+
+ @Test
+ public void should_perform_shallow_merge() throws Exception {
+ Toml toml = new Toml(defaultToml).parse("[group]\nb=1\n [[array]]\n b=0");
+ Toml toml2 = new Toml(defaultToml).parse("[[array]]\n b=1 [[array]]\n b=2 [[array]]\n b=3");
assertEquals(1, toml.getTable("group").getLong("b").intValue());
- assertEquals("a", toml.getTable("group").getString("a"));
+ assertNull(toml.getTable("group").getString("a"));
+ assertThat(toml.getTables("array"), hasSize(1));
+ assertEquals(0, toml.getLong("array[0].b").intValue());
+ assertThat(toml2.getTables("array"), hasSize(3));
}
}
diff --git a/src/test/java/com/moandjiezana/toml/testutils/ExtraPrimitives.java b/src/test/java/com/moandjiezana/toml/testutils/ExtraPrimitives.java
index f0ddd7f..b5d0ab9 100644
--- a/src/test/java/com/moandjiezana/toml/testutils/ExtraPrimitives.java
+++ b/src/test/java/com/moandjiezana/toml/testutils/ExtraPrimitives.java
@@ -3,6 +3,7 @@ package com.moandjiezana.toml.testutils;
import java.lang.annotation.ElementType;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.net.URI;
import java.net.URL;
import java.util.Map;
import java.util.Set;
@@ -17,5 +18,6 @@ public class ExtraPrimitives {
public Character character;
public ElementType elementType;
public URL url;
+ public URI uri;
public Set set;
}
diff --git a/src/test/resources/com/moandjiezana/toml/should_convert_extra_primitives.toml b/src/test/resources/com/moandjiezana/toml/should_convert_extra_primitives.toml
index 33c2a30..359e027 100644
--- a/src/test/resources/com/moandjiezana/toml/should_convert_extra_primitives.toml
+++ b/src/test/resources/com/moandjiezana/toml/should_convert_extra_primitives.toml
@@ -5,6 +5,7 @@ anInteger=7
character="u"
elementType="CONSTRUCTOR"
url="http://www.example.com"
+uri="http://www.test.com"
set=["a", "b"]
[group]
key="value"