Skip to content

Commit

Permalink
Deprecated settings API for complete overhaul in 4.0
Browse files Browse the repository at this point in the history
Renamed isReloadable to Dynamic and maid it an annotation instead
  • Loading branch information
klaren committed Aug 15, 2017
1 parent 0729574 commit 7656615
Show file tree
Hide file tree
Showing 16 changed files with 199 additions and 90 deletions.
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2002-2017 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.configuration;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Dynamic properties can be changed at runtime.
*/
@Retention( RetentionPolicy.RUNTIME )
@Target( {ElementType.TYPE, ElementType.FIELD} )
public @interface Dynamic
{
}
Expand Up @@ -75,6 +75,9 @@ default List<ConfigOptions> getConfigOptions()

final Internal internalAnnotation = f.getAnnotation( Internal.class );
setting.setInternal( internalAnnotation != null );

final Dynamic dynamicAnnotation = f.getAnnotation( Dynamic.class );
setting.setDynamic( dynamicAnnotation != null );
}

if ( publicSetting instanceof SettingGroup )
Expand Down
Expand Up @@ -29,48 +29,66 @@
import org.neo4j.graphdb.config.BaseSetting;
import org.neo4j.graphdb.config.Configuration;
import org.neo4j.graphdb.config.Setting;
import org.neo4j.helpers.collection.MapUtil;
import org.neo4j.graphdb.config.SettingGroup;

import static java.util.Collections.emptyMap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.neo4j.helpers.collection.MapUtil.stringMap;

public class LoadableConfigTest
{
@Test
public void getConfigOptions() throws Exception
{
Map<String,String> config = MapUtil.stringMap( "myInt", "123", "myString", "bah", "myOldString", "moo" );
Map<String,String> config = stringMap(
TestConfig.integer.name(), "123",
TestConfig.string.name(), "bah",
TestConfig.oldString.name(), "moo",
TestConfig.dynamic.name(), "foo" );

TestConfig testSettings = new TestConfig();

List<ConfigOptions> options = testSettings.getConfigOptions();

assertEquals( 3, options.size() );

assertEquals( 1, options.get( 0 ).settingGroup().values( emptyMap() ).get( "myInt" ) );
assertEquals( 123, options.get( 0 ).settingGroup().values( config ).get( "myInt" ) );
assertEquals( Optional.empty(), options.get( 0 ).settingGroup().description() );
assertFalse( options.get(0).settingGroup().deprecated() );
assertEquals( Optional.empty(), options.get( 0 ).settingGroup().replacement() );

assertEquals( "bob", options.get( 1 ).settingGroup().values( emptyMap() ).get( "myString" ) );
assertEquals( "bah", options.get( 1 ).settingGroup().values( config ).get( "myString" ) );
assertEquals( "A string setting", options.get( 1 ).settingGroup().description().get() );
assertFalse( options.get(1).settingGroup().deprecated() );
assertEquals( Optional.empty(), options.get( 1 ).settingGroup().replacement() );

assertEquals( "tim", options.get( 2 ).settingGroup().values( emptyMap() ).get( "myOldString" ) );
assertEquals( "moo", options.get( 2 ).settingGroup().values( config ).get( "myOldString" ) );
assertEquals( "A deprecated string setting", options.get( 2 ).settingGroup().description().get() );
assertTrue( options.get(2).settingGroup().deprecated() );
assertEquals( "myString", options.get( 2 ).settingGroup().replacement().get() );
assertEquals( 4, options.size() );

SettingGroup<?> integerSetting = options.get( 0 ).settingGroup();
assertEquals( 1, integerSetting.values( emptyMap() ).get( TestConfig.integer.name() ) );
assertEquals( 123, integerSetting.values( config ).get( TestConfig.integer.name() ) );
assertEquals( Optional.empty(), integerSetting.description() );
assertFalse( integerSetting.deprecated() );
assertFalse( integerSetting.dynamic() );
assertEquals( Optional.empty(), integerSetting.replacement() );

SettingGroup<?> stringSetting = options.get( 1 ).settingGroup();
assertEquals( "bob", stringSetting.values( emptyMap() ).get( TestConfig.string.name() ) );
assertEquals( "bah", stringSetting.values( config ).get( TestConfig.string.name() ) );
assertEquals( "A string setting", stringSetting.description().get() );
assertFalse( stringSetting.deprecated() );
assertFalse( stringSetting.dynamic() );
assertEquals( Optional.empty(), stringSetting.replacement() );

SettingGroup<?> oldStringSetting = options.get( 2 ).settingGroup();
assertEquals( "tim", oldStringSetting.values( emptyMap() ).get( TestConfig.oldString.name() ) );
assertEquals( "moo", oldStringSetting.values( config ).get( TestConfig.oldString.name() ) );
assertEquals( "A deprecated string setting", oldStringSetting.description().get() );
assertTrue( oldStringSetting.deprecated() );
assertFalse( oldStringSetting.dynamic() );
assertEquals( TestConfig.string.name(), oldStringSetting.replacement().get() );

SettingGroup<?> dynamicSetting = options.get( 3 ).settingGroup();
assertEquals( "defaultDynamic", dynamicSetting.values( emptyMap() ).get( TestConfig.dynamic.name() ) );
assertEquals( "foo", dynamicSetting.values( config ).get( TestConfig.dynamic.name() ) );
assertEquals( "A dynamic string setting", dynamicSetting.description().get() );
assertFalse( dynamicSetting.deprecated() );
assertTrue( dynamicSetting.dynamic() );
assertEquals( Optional.empty(), dynamicSetting.replacement() );
}

private static class TestConfig implements LoadableConfig
{
@SuppressWarnings( "unused" )
public static final Setting<Integer> integer = new BaseSetting<Integer>()
{
@Override
Expand Down Expand Up @@ -116,7 +134,6 @@ public Integer apply( Function<String,String> provider )

};

@SuppressWarnings( "unused" )
@Description( "A string setting" )
public static final Setting<String> string = new StringSetting()
{
Expand Down Expand Up @@ -156,7 +173,6 @@ public String from( Configuration configuration )
}
};

@SuppressWarnings( "unused" )
@Description( "A deprecated string setting" )
@Deprecated
@ReplacedBy( "myString" )
Expand Down Expand Up @@ -232,16 +248,50 @@ public String from( Configuration configuration )
return configuration.get( this );
}
};

@Description( "A dynamic string setting" )
@Dynamic
public static final Setting<String> dynamic = new StringSetting()
{
@Override
public String apply( Function<String,String> provider )
{
String val = provider.apply( name() );
if ( val == null )
{
val = getDefaultValue();
}
return val;
}

@Override
public String name()
{
return "myDynamicProperty";
}

@Override
public void withScope( Function<String,String> scopingRule )
{

}

@Override
public String getDefaultValue()
{
return "defaultDynamic";
}

@Override
public String from( Configuration configuration )
{
return configuration.get( this );
}
};
}

private abstract static class StringSetting extends BaseSetting<String>
{
@Override
public boolean isReloadable()
{
return false;
}

@Override
public String valueDescription()
{
Expand Down
Expand Up @@ -24,12 +24,15 @@

/**
* All fields specified here are set via annotations when loaded
* @deprecated The settings API will be completely rewritten in 4.0
*/
@Deprecated
public abstract class BaseSetting<T> implements Setting<T>
{
private boolean deprecated;
private String replacement;
private boolean internal;
private boolean dynamic;
private String documentedDefaultValue;
private String description;

Expand Down Expand Up @@ -93,4 +96,21 @@ public String toString()
{
return valueDescription();
}

/**
* Checks whether this setting is dynamic or not. Dynamic properties are allowed to be changed at runtime without
* restarting the server.
*
* @return {@code true} if this setting can be changed at runtime.
*/
@Override
public boolean dynamic()
{
return dynamic;
}

public void setDynamic( boolean dynamic )
{
this.dynamic = dynamic;
}
}
Expand Up @@ -21,7 +21,9 @@

/**
* Provide the basic operation that one could perform on a set of configurations.
* @deprecated The settings API will be completely rewritten in 4.0
*/
@Deprecated
public interface Configuration
{
/**
Expand Down
Expand Up @@ -21,7 +21,9 @@

/**
* Thrown when a configuration setting is, for one reason or another, invalid.
* @deprecated The settings API will be completely rewritten in 4.0
*/
@Deprecated
public class InvalidSettingException extends RuntimeException
{

Expand Down
Expand Up @@ -21,6 +21,10 @@

import java.util.function.Function;

/**
* @deprecated The settings API will be completely rewritten in 4.0
*/
@Deprecated
public abstract class ScopeAwareSetting<T> extends BaseSetting<T>
{
private Function<String,String> scopingRule = Function.identity();
Expand Down
Expand Up @@ -33,12 +33,14 @@
/**
* Settings that can be provided in configurations are represented by instances of this interface, and are available
* as static fields in various *Settings classes.
*
* <p>
* This interface is available only for use, not for implementing. Implementing this interface is not expected, and
* backwards compatibility is not guaranteed for implementors.
*
* @param <T> type of value this setting will parse input string into and return.
* @deprecated The settings API will be completely rewritten in 4.0
*/
@Deprecated
public interface Setting<T> extends Function<Function<String,String>,T>, SettingValidator, SettingGroup<T>
{
/**
Expand Down Expand Up @@ -106,13 +108,8 @@ default List<Setting<T>> settings( Map<String,String> params )
*
* @return the parser function
*/
default Optional<Function<String, T>> getParser()
default Optional<Function<String,T>> getParser()
{
return Optional.empty();
}

default boolean isReloadable()
{
return false;
}
}
Expand Up @@ -26,55 +26,60 @@
/**
* This interface represents a setting group. One example can be group defined by a common prefix, such as
* `dbms.connector.*`. The important aspect is that config keys can only be known after a config has been parsed.
*
* @deprecated The settings API will be completely rewritten in 4.0
*/
@Deprecated
public interface SettingGroup<T> extends SettingValidator
{
/**
* Apply this setting group to the config and return all of its configured keys and their corresponding values.
*
* @param validConfig which can be examined
* @return the map of this group's configured keys and values
* @param validConfig which can be examined.
* @return the map of this group's configured keys and values.
*/
Map<String,T> values( Map<String,String> validConfig );

/**
* @return a list of the settings this group contains
* @return a list of the settings this group contains.
*/
List<Setting<T>> settings( Map<String,String> params );

/**
*
* @return true if this setting is deprecated, false otherwise
* @return {@code true} if this setting is deprecated, false otherwise.
*/
boolean deprecated();

/**
*
* @return the key of the setting which replaces this when its deprecated, empty if not depricated
* @return the key of the setting which replaces this when its deprecated, empty if not deprecated.
*/
Optional<String> replacement();

/**
*
* @return true if internal setting, false otherwise
* @return {@code true} if internal setting, false otherwise.
*/
boolean internal();

/**
*
* @return the documented default value if it needs special documentation, empty if default value is good as is
* @return the documented default value if it needs special documentation, empty if default value is good as is.
*/
Optional<String> documentedDefaultValue();

/**
*
* @return description of which values are good
*/
String valueDescription();

/**
*
* @return description of setting, empty in case no description exists
* @return description of setting, empty in case no description exists.
*/
Optional<String> description();

/**
* @return {@code true} if the setting can be changed at runtime.
*/
default boolean dynamic()
{
return false;
}
}
Expand Up @@ -22,6 +22,10 @@
import java.util.Map;
import java.util.function.Consumer;

/**
* @deprecated The settings API will be completely rewritten in 4.0
*/
@Deprecated
public interface SettingValidator
{
/**
Expand Down

0 comments on commit 7656615

Please sign in to comment.