#1934: Better in memory config representation
This commit is contained in:
parent
d6772cf1e4
commit
37b3cb4a30
@ -7,10 +7,7 @@ import java.util.Collections;
|
|||||||
import java.util.LinkedHashMap;
|
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.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
|
||||||
public final class Configuration
|
public final class Configuration
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -28,6 +25,25 @@ public final class Configuration
|
|||||||
this( new LinkedHashMap<String, Object>(), defaults );
|
this( new LinkedHashMap<String, Object>(), defaults );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Configuration(Map<?, ?> map, Configuration defaults)
|
||||||
|
{
|
||||||
|
this.self = new LinkedHashMap<>();
|
||||||
|
this.defaults = defaults;
|
||||||
|
|
||||||
|
for ( Map.Entry<?, ?> entry : map.entrySet() )
|
||||||
|
{
|
||||||
|
String key = entry.getKey().toString();
|
||||||
|
|
||||||
|
if ( entry.getValue() instanceof Map )
|
||||||
|
{
|
||||||
|
this.self.put( key, new Configuration( (Map) entry.getValue(), ( defaults == null ) ? null : defaults.getSection( key ) ) );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
this.self.put( key, entry.getValue() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Configuration getSectionFor(String path)
|
private Configuration getSectionFor(String path)
|
||||||
{
|
{
|
||||||
int index = path.indexOf( SEPARATOR );
|
int index = path.indexOf( SEPARATOR );
|
||||||
@ -40,15 +56,11 @@ public final class Configuration
|
|||||||
Object section = self.get( root );
|
Object section = self.get( root );
|
||||||
if ( section == null )
|
if ( section == null )
|
||||||
{
|
{
|
||||||
section = new LinkedHashMap<>();
|
section = new Configuration( ( defaults == null ) ? null : defaults.getSection( path ) );
|
||||||
self.put( root, section );
|
self.put( root, section );
|
||||||
}
|
}
|
||||||
if ( section instanceof Configuration )
|
|
||||||
{
|
|
||||||
return (Configuration) section;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Configuration( (Map) section, ( defaults == null ) ? null : defaults.getSectionFor( path ) );
|
return (Configuration) section;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getChild(String path)
|
private String getChild(String path)
|
||||||
@ -71,6 +83,11 @@ public final class Configuration
|
|||||||
val = section.get( getChild( path ), def );
|
val = section.get( getChild( path ), def );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( val == null && def instanceof Configuration )
|
||||||
|
{
|
||||||
|
self.put( path, def );
|
||||||
|
}
|
||||||
|
|
||||||
return ( val != null ) ? (T) val : def;
|
return ( val != null ) ? (T) val : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +123,7 @@ public final class Configuration
|
|||||||
public Configuration getSection(String path)
|
public Configuration getSection(String path)
|
||||||
{
|
{
|
||||||
Object def = getDefault( path );
|
Object def = getDefault( path );
|
||||||
return new Configuration( (Map) ( get( path, ( def instanceof Map ) ? def : Collections.EMPTY_MAP ) ), ( defaults == null ) ? null : defaults.getSection( path ) );
|
return (Configuration) get( path, ( def instanceof Configuration ) ? def : new Configuration( ( defaults == null ) ? null : defaults.getSection( path ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,6 +13,10 @@ import lombok.AccessLevel;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.yaml.snakeyaml.DumperOptions;
|
import org.yaml.snakeyaml.DumperOptions;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
import org.yaml.snakeyaml.constructor.Constructor;
|
||||||
|
import org.yaml.snakeyaml.nodes.Node;
|
||||||
|
import org.yaml.snakeyaml.representer.Represent;
|
||||||
|
import org.yaml.snakeyaml.representer.Representer;
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PACKAGE)
|
@NoArgsConstructor(access = AccessLevel.PACKAGE)
|
||||||
public class YamlConfiguration extends ConfigurationProvider
|
public class YamlConfiguration extends ConfigurationProvider
|
||||||
@ -23,9 +27,24 @@ public class YamlConfiguration extends ConfigurationProvider
|
|||||||
@Override
|
@Override
|
||||||
protected Yaml initialValue()
|
protected Yaml initialValue()
|
||||||
{
|
{
|
||||||
|
Representer representer = new Representer()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
representers.put( Configuration.class, new Represent()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Node representData(Object data)
|
||||||
|
{
|
||||||
|
return represent( ( (Configuration) data ).self );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
DumperOptions options = new DumperOptions();
|
DumperOptions options = new DumperOptions();
|
||||||
options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK );
|
options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK );
|
||||||
return new Yaml( options );
|
|
||||||
|
return new Yaml( new Constructor(), representer, options );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import org.junit.Test;
|
|||||||
public class YamlConfigurationTest
|
public class YamlConfigurationTest
|
||||||
{
|
{
|
||||||
|
|
||||||
private String document = ""
|
private static final String TEST_DOCUMENT = ""
|
||||||
+ "receipt: Oz-Ware Purchase Invoice\n"
|
+ "receipt: Oz-Ware Purchase Invoice\n"
|
||||||
+ "date: 2012-08-06\n"
|
+ "date: 2012-08-06\n"
|
||||||
+ "customer:\n"
|
+ "customer:\n"
|
||||||
@ -43,11 +43,17 @@ public class YamlConfigurationTest
|
|||||||
+ " Road to the Emerald City.\n"
|
+ " Road to the Emerald City.\n"
|
||||||
+ " Pay no attention to the\n"
|
+ " Pay no attention to the\n"
|
||||||
+ " man behind the curtain.";
|
+ " man behind the curtain.";
|
||||||
|
private static final String NUMBER_TEST = ""
|
||||||
|
+ "someKey:\n"
|
||||||
|
+ " 1: 1\n"
|
||||||
|
+ " 2: 2\n"
|
||||||
|
+ " 3: 3\n"
|
||||||
|
+ " 4: 4";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConfig() throws Exception
|
public void testConfig() throws Exception
|
||||||
{
|
{
|
||||||
Configuration conf = ConfigurationProvider.getProvider( YamlConfiguration.class ).load( document );
|
Configuration conf = ConfigurationProvider.getProvider( YamlConfiguration.class ).load( TEST_DOCUMENT );
|
||||||
testSection( conf );
|
testSection( conf );
|
||||||
|
|
||||||
StringWriter sw = new StringWriter();
|
StringWriter sw = new StringWriter();
|
||||||
@ -77,5 +83,24 @@ public class YamlConfigurationTest
|
|||||||
conf.set( "receipt", null );
|
conf.set( "receipt", null );
|
||||||
Assert.assertEquals( null, conf.get( "receipt" ) );
|
Assert.assertEquals( null, conf.get( "receipt" ) );
|
||||||
Assert.assertEquals( "foo", conf.get( "receipt", "foo" ) );
|
Assert.assertEquals( "foo", conf.get( "receipt", "foo" ) );
|
||||||
|
|
||||||
|
Configuration newSection = conf.getSection( "new.section" );
|
||||||
|
newSection.set( "value", "foo" );
|
||||||
|
Assert.assertEquals( "foo", conf.get( "new.section.value" ) );
|
||||||
|
|
||||||
|
conf.set( "other.new.section", "bar" );
|
||||||
|
Assert.assertEquals( "bar", conf.get( "other.new.section" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNumberedKeys()
|
||||||
|
{
|
||||||
|
Configuration conf = ConfigurationProvider.getProvider( YamlConfiguration.class ).load( NUMBER_TEST );
|
||||||
|
|
||||||
|
Configuration section = conf.getSection( "someKey" );
|
||||||
|
for ( String key : section.getKeys() )
|
||||||
|
{
|
||||||
|
// empty
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user