Finish basic Yaml configuration API, complete with unit tests. Needs a lot of work with regards to how sections are handled, open to massive improvements from anyone that has more know-how.

This commit is contained in:
md_5 2013-09-23 10:28:30 +10:00
parent 8133304cce
commit a8b6a6b4aa
8 changed files with 126 additions and 46 deletions

View File

@ -25,6 +25,12 @@
<version>14.0.1</version> <version>14.0.1</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-event</artifactId> <artifactId>bungeecord-event</artifactId>
@ -37,11 +43,5 @@
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.12</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -19,16 +19,11 @@
<description>Generic java configuration API intended for use with BungeeCord</description> <description>Generic java configuration API intended for use with BungeeCord</description>
<dependencies> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.yaml</groupId> <groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
<version>1.11</version> <version>1.13</version>
<scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -2,7 +2,7 @@ package net.md_5.bungee.config;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import lombok.AccessLevel; import lombok.AccessLevel;
@ -14,35 +14,52 @@ public final class Configuration
private static final char SEPARATOR = '.'; private static final char SEPARATOR = '.';
private final Map<String, Object> self; private final Map<String, Object> self;
private Map<String, Object> comments = new HashMap<>();
private final Configuration defaults; private final Configuration defaults;
private Map<String, Object> getHolder(String path, Map<String, Object> parent, boolean create) private Configuration getSectionFor(String path)
{
return null;
}
private Object get(String path, Map<String, Object> holder)
{ {
int index = path.indexOf( SEPARATOR ); int index = path.indexOf( SEPARATOR );
String first, second;
if ( index == -1 ) if ( index == -1 )
{ {
second = path; return this;
} else
{
first = path.substring( 0, index );
second = path.substring( index + 1, path.length() );
} }
return null;
String root = path.substring( 0, index );
Object section = self.get( root );
if ( section == null )
{
section = new LinkedHashMap<>();
self.put( root, section );
}
if ( section instanceof Configuration )
{
return (Configuration) section;
}
return new Configuration( (Map) section, ( defaults == null ) ? null : defaults.getSectionFor( path ) );
}
private String getChild(String path)
{
int index = path.indexOf( SEPARATOR );
return ( index == -1 ) ? path : path.substring( index + 1 );
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T get(String path, T def) public <T> T get(String path, T def)
{ {
Object val = get( path, self ); Configuration section = getSectionFor( path );
return ( val != null && val.getClass().isInstance( def ) ) ? (T) val : (T) defaults.get( path ); Object val;
if ( section == this )
{
val = self.get( path );
} else
{
val = section.get( getChild( path ), def );
}
return ( val != null ) ? (T) val : def;
} }
public Object get(String path) public Object get(String path)
@ -52,19 +69,26 @@ public final class Configuration
public Object getDefault(String path) public Object getDefault(String path)
{ {
return defaults.get( path ); return ( defaults == null ) ? null : defaults.get( path );
}
public void set(String path, Object value, String comment)
{
String child = path.substring( path.indexOf( SEPARATOR ) + 1 );
getHolder( path, self, true ).put( child, value );
getHolder( path, comments, true ).put( child, value );
} }
public void set(String path, Object value) public void set(String path, Object value)
{ {
set( path, value, null ); Configuration section = getSectionFor( path );
if ( section == this )
{
self.put( path, value );
} else
{
section.set( getChild( path ), value );
}
}
/*------------------------------------------------------------------------*/
public Configuration getSection(String path)
{
Object def = getDefault( path );
return new Configuration( (Map) ( get( path, ( def instanceof Map ) ? def : Collections.EMPTY_MAP ) ), ( defaults == null ) ? null : defaults.getSection( path ) );
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/

View File

@ -15,7 +15,7 @@ public abstract class ConfigurationProvider
providers.put( YamlConfiguration.class, new YamlConfiguration() ); providers.put( YamlConfiguration.class, new YamlConfiguration() );
} }
public ConfigurationProvider getProvider(Class<? extends ConfigurationProvider> provider) public static ConfigurationProvider getProvider(Class<? extends ConfigurationProvider> provider)
{ {
return providers.get( provider ); return providers.get( provider );
} }

View File

@ -1,7 +1,6 @@
package net.md_5.bungee.config; package net.md_5.bungee.config;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
@ -9,7 +8,7 @@ import java.util.Map;
import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
public class YamlConfiguration extends ConfigurationProvider class YamlConfiguration extends ConfigurationProvider
{ {
private final ThreadLocal<Yaml> yaml = new ThreadLocal<Yaml>() private final ThreadLocal<Yaml> yaml = new ThreadLocal<Yaml>()

View File

@ -0,0 +1,61 @@
package net.md_5.bungee.config;
import java.util.List;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
public class YamlConfigurationTest
{
private String docuement = ""
+ "receipt: Oz-Ware Purchase Invoice\n"
+ "date: 2012-08-06\n"
+ "customer:\n"
+ " given: Dorothy\n"
+ " family: Gale\n"
+ "\n"
+ "items:\n"
+ " - part_no: A4786\n"
+ " descrip: Water Bucket (Filled)\n"
+ " price: 1.47\n"
+ " quantity: 4\n"
+ "\n"
+ " - part_no: E1628\n"
+ " descrip: High Heeled \"Ruby\" Slippers\n"
+ " size: 8\n"
+ " price: 100.27\n"
+ " quantity: 1\n"
+ "\n"
+ "bill-to: &id001\n"
+ " street: |\n"
+ " 123 Tornado Alley\n"
+ " Suite 16\n"
+ " city: East Centerville\n"
+ " state: KS\n"
+ "\n"
+ "ship-to: *id001\n"
+ "\n"
+ "specialDelivery: >\n"
+ " Follow the Yellow Brick\n"
+ " Road to the Emerald City.\n"
+ " Pay no attention to the\n"
+ " man behind the curtain.";
@Test
public void testRead() throws Exception
{
Configuration conf = ConfigurationProvider.getProvider( YamlConfiguration.class ).load( docuement );
Assert.assertEquals( "receipt", "Oz-Ware Purchase Invoice", conf.getString( "receipt" ) );
// Assert.assertEquals( "date", "2012-08-06", conf.get( "date" ).toString() );
Configuration customer = conf.getSection( "customer" );
Assert.assertEquals( "customer.given", "Dorothy", customer.getString( "given" ) );
Assert.assertEquals( "customer.given", "Dorothy", conf.getString( "customer.given" ) );
List items = conf.getList( "items" );
Map item = (Map) items.get( 0 );
Assert.assertEquals( "items[0].part_no", "A4786", item.get( "part_no" ) );
}
}

View File

@ -38,6 +38,7 @@
<modules> <modules>
<module>api</module> <module>api</module>
<module>config</module>
<module>event</module> <module>event</module>
<module>protocol</module> <module>protocol</module>
<module>proxy</module> <module>proxy</module>

View File

@ -19,7 +19,7 @@
<description>Proxy component of the Elastic Portal Suite</description> <description>Proxy component of the Elastic Portal Suite</description>
<properties> <properties>
<maven.build.timestamp.format>yyyyMMdd</maven.build.timestamp.format> <maven.build.timestamp.format>yyyyMMdd</maven.build.timestamp.format>
</properties> </properties>
<dependencies> <dependencies>
@ -43,13 +43,13 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-protocol</artifactId> <artifactId>bungeecord-api</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId> <artifactId>bungeecord-protocol</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
@ -97,7 +97,7 @@
<configuration> <configuration>
<archive> <archive>
<manifestEntries> <manifestEntries>
<Main-Class>net.md_5.bungee.BungeeCord</Main-Class> <Main-Class>net.md_5.bungee.Bootstrap</Main-Class>
<Implementation-Version>${describe}</Implementation-Version> <Implementation-Version>${describe}</Implementation-Version>
<Specification-Version>${maven.build.timestamp}</Specification-Version> <Specification-Version>${maven.build.timestamp}</Specification-Version>
</manifestEntries> </manifestEntries>