mirror of
https://github.com/plexusorg/toml4j.git
synced 2025-01-01 13:02:37 +00:00
Added javadoc. Better null-handling and return empty containers instead
of null.
This commit is contained in:
parent
1773bd5d1e
commit
86257278b7
3 changed files with 123 additions and 21 deletions
9
pom.xml
9
pom.xml
|
@ -1,4 +1,5 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.sonatype.oss</groupId>
|
<groupId>org.sonatype.oss</groupId>
|
||||||
|
@ -40,6 +41,12 @@
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.2.2</version>
|
<version>2.2.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.easytesting</groupId>
|
||||||
|
<artifactId>fest-reflect</artifactId>
|
||||||
|
<version>1.4.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.moandjiezana.toml;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -16,8 +17,20 @@ import org.parboiled.support.ParsingResult;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <p>Provides access to the keys and tables in a TOML data source.</p>
|
||||||
*
|
*
|
||||||
* All getters can fall back to default values if they have been provided and will return null if no matching key exists.
|
* <p>All getters can fall back to default values if they have been provided.
|
||||||
|
* Getters for simple values (String, Date, etc.) will return null if no matching key exists.
|
||||||
|
* {@link #getList(String, Class)}, {@link #getTable(String)} and {@link #getTables(String)} return empty values if there is no matching key.</p>
|
||||||
|
*
|
||||||
|
* <p>Example usage:</p>
|
||||||
|
* <code><pre>
|
||||||
|
* Toml toml = new Toml().parse(getTomlFile());
|
||||||
|
* String name = toml.getString("name");
|
||||||
|
* Long port = toml.getLong("server.ip"); // compound key. Is equivalent to:
|
||||||
|
* Long port2 = toml.getTable("server").getLong("ip");
|
||||||
|
* MyConfig config = toml.to(MyConfig.class);
|
||||||
|
* </pre></code>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Toml {
|
public class Toml {
|
||||||
|
@ -25,23 +38,50 @@ public class Toml {
|
||||||
private Map<String, Object> values = new HashMap<String, Object>();
|
private Map<String, Object> values = new HashMap<String, Object>();
|
||||||
private final Toml defaults;
|
private final Toml defaults;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates Toml instance with no defaults.
|
||||||
|
*/
|
||||||
public Toml() {
|
public Toml() {
|
||||||
this((Toml) null);
|
this((Toml) null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param defaults fallback values used when the requested key or table is not present.
|
||||||
|
*/
|
||||||
public Toml(Toml defaults) {
|
public Toml(Toml defaults) {
|
||||||
this.defaults = defaults;
|
this.defaults = defaults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the current Toml instance with values from tomlString.
|
||||||
|
*
|
||||||
|
* @param file
|
||||||
|
* @return this instance
|
||||||
|
* @throws IllegalStateException If file contains invalid TOML
|
||||||
|
*/
|
||||||
public Toml parse(File file) {
|
public Toml parse(File file) {
|
||||||
|
Scanner scanner = null;
|
||||||
try {
|
try {
|
||||||
return parse(new Scanner(file).useDelimiter("\\Z").next());
|
scanner = new Scanner(file);
|
||||||
|
|
||||||
|
return parse(scanner.useDelimiter("\\Z").next());
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
if (scanner != null) {
|
||||||
|
scanner.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Toml parse(String tomlString) {
|
/**
|
||||||
|
* Populates the current Toml instance with values from tomlString.
|
||||||
|
*
|
||||||
|
* @param tomlString
|
||||||
|
* @return this instance
|
||||||
|
* @throws IllegalStateException If tomlString is not valid TOML
|
||||||
|
*/
|
||||||
|
public Toml parse(String tomlString) throws IllegalStateException {
|
||||||
TomlParser parser = Parboiled.createParser(TomlParser.class);
|
TomlParser parser = Parboiled.createParser(TomlParser.class);
|
||||||
ParsingResult<Object> result = new RecoveringParseRunner<Object>(parser.Toml()).run(tomlString);
|
ParsingResult<Object> result = new RecoveringParseRunner<Object>(parser.Toml()).run(tomlString);
|
||||||
// ParsingResult<Object> parsingResult = new ReportingParseRunner<Object>(parser.Toml()).run(tomlString);
|
// ParsingResult<Object> parsingResult = new ReportingParseRunner<Object>(parser.Toml()).run(tomlString);
|
||||||
|
@ -67,7 +107,13 @@ public class Toml {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> List<T> getList(String key, Class<T> itemClass) {
|
public <T> List<T> getList(String key, Class<T> itemClass) {
|
||||||
return (List<T>) get(key);
|
List<T> list = (List<T>) get(key);
|
||||||
|
|
||||||
|
if (list == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getBoolean(String key) {
|
public Boolean getBoolean(String key) {
|
||||||
|
@ -82,21 +128,59 @@ public class Toml {
|
||||||
return (Double) get(key);
|
return (Double) get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If no value is found for key, an empty Toml instance is returned.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Toml getTable(String key) {
|
public Toml getTable(String key) {
|
||||||
return new Toml((Map<String, Object>) get(key));
|
return new Toml((Map<String, Object>) get(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If no value is found for key, an empty list is returned.
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public List<Toml> getTables(String key) {
|
public List<Toml> getTables(String key) {
|
||||||
|
List<Map<String, Object>> tableArray = (List<Map<String, Object>>) get(key);
|
||||||
|
|
||||||
|
if (tableArray == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
ArrayList<Toml> tables = new ArrayList<Toml>();
|
ArrayList<Toml> tables = new ArrayList<Toml>();
|
||||||
for (Map<String, Object> table : (List<Map<String, Object>>) get(key)) {
|
for (Map<String, Object> table : tableArray) {
|
||||||
tables.add(new Toml(table));
|
tables.add(new Toml(table));
|
||||||
}
|
}
|
||||||
|
|
||||||
return tables;
|
return tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Populates an instance of targetClass with the values of this Toml instance.
|
||||||
|
* The target's field names must match keys or tables.
|
||||||
|
* Keys not present in targetClass will be ignored.</p>
|
||||||
|
*
|
||||||
|
* <p>Tables are recursively converted to custom classes.</p>
|
||||||
|
*
|
||||||
|
* @param targetClass
|
||||||
|
*/
|
||||||
|
public <T> T to(Class<T> targetClass) {
|
||||||
|
HashMap<String, Object> valuesCopy = new HashMap<String, Object>(values);
|
||||||
|
if (defaults != null) {
|
||||||
|
for (Map.Entry<String, Object> entry : defaults.values.entrySet()) {
|
||||||
|
if (!valuesCopy.containsKey(entry.getKey())) {
|
||||||
|
valuesCopy.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Gson gson = new Gson();
|
||||||
|
String json = gson.toJson(valuesCopy);
|
||||||
|
return gson.fromJson(json, targetClass);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Object get(String key) {
|
private Object get(String key) {
|
||||||
String[] split = key.split("\\.");
|
String[] split = key.split("\\.");
|
||||||
|
@ -126,21 +210,7 @@ public class Toml {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Toml(Map<String, Object> values) {
|
private Toml(Map<String, Object> values) {
|
||||||
this.values = values;
|
this.values = values != null ? values : Collections.<String, Object>emptyMap();
|
||||||
this.defaults = null;
|
this.defaults = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T to(Class<T> targetClass) {
|
|
||||||
HashMap<String, Object> valuesCopy = new HashMap<String, Object>(values);
|
|
||||||
if (defaults != null) {
|
|
||||||
for (Map.Entry<String, Object> entry : defaults.values.entrySet()) {
|
|
||||||
if (!valuesCopy.containsKey(entry.getKey())) {
|
|
||||||
valuesCopy.put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Gson gson = new Gson();
|
|
||||||
String json = gson.toJson(valuesCopy);
|
|
||||||
return gson.fromJson(json, targetClass);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,11 @@ import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import org.fest.reflect.core.Reflection;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -129,6 +132,13 @@ public class TomlTest {
|
||||||
assertNull(toml.getString("a"));
|
assertNull(toml.getString("a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void should_return_empty_list_if_no_value_for_key() throws Exception {
|
||||||
|
Toml toml = new Toml().parse("");
|
||||||
|
|
||||||
|
assertTrue(toml.getList("a", String.class).isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void should_return_null_when_no_value_for_multi_key() throws Exception {
|
public void should_return_null_when_no_value_for_multi_key() throws Exception {
|
||||||
Toml toml = new Toml().parse("");
|
Toml toml = new Toml().parse("");
|
||||||
|
@ -136,6 +146,21 @@ public class TomlTest {
|
||||||
assertNull(toml.getString("group.key"));
|
assertNull(toml.getString("group.key"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void should_return_empty_toml_when_no_value_for_table() throws Exception {
|
||||||
|
Toml toml = new Toml().parse("[a]").getTable("b");
|
||||||
|
|
||||||
|
assertTrue(Reflection.field("values").ofType(Map.class).in(toml).get().isEmpty());
|
||||||
|
assertNull(toml.getString("x"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void should_return_empty_list_when_no_value_for_table_array() throws Exception {
|
||||||
|
List<Toml> tomls = new Toml().parse("[a]").getTables("b");
|
||||||
|
|
||||||
|
assertTrue(tomls.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void should_load_from_file() throws Exception {
|
public void should_load_from_file() throws Exception {
|
||||||
Toml toml = new Toml().parse(new File(getClass().getResource("should_load_from_file.toml").getFile()));
|
Toml toml = new Toml().parse(new File(getClass().getResource("should_load_from_file.toml").getFile()));
|
||||||
|
|
Loading…
Reference in a new issue