
io.fabric8.maven.docker.config.handler.property.ValueProvider Maven / Gradle / Ivy
The newest version!
package io.fabric8.maven.docker.config.handler.property;
import java.util.*;
import io.fabric8.maven.docker.util.EnvUtil;
import static io.fabric8.maven.docker.util.EnvUtil.*;
/**
* Helper to extract values from a set of Properties, potentially mixing it up with XML-based configuration based on the
* {@link PropertyMode} setting.
*
* Obtaining a value is done via data-type specific methods (such as {@link #getString}). The ConfigKey parameter
* tells us which property to look for, and how to handle combination of multiple values.
*
* For {@link PropertyMode#Only} we only look at the properties, ignoring any config value.
* For {@link PropertyMode#Skip} we only look at the config, ignoring any properties value.
* For {@link PropertyMode#Override} we use the property value if it is non-null, else the config value.
* For {@link PropertyMode#Fallback} we use the config value if it is non-null, else the property value.
*
* For Override and Fallback mode, merging may take place as dictated by the {@link ValueCombinePolicy}
* defined in the {@link ConfigKey}, or as overridden by the property <prefix.someproperty>._combine
* ({@link EnvUtil#PROPERTY_COMBINE_POLICY_SUFFIX}).
*
* If {@link ValueCombinePolicy#Replace} is used, only the prioritized value (first non-null) is used.
* If {@link ValueCombinePolicy#Merge} is used, the merge method depends on the data type.
* For simple types (string, int, long, boolean) this is not supported and will throw exception.
* For Lists, the non-null values will be appended to each other (with values from first source added first)
* For Maps, all maps are merged into one map, with data from the first map taking precedence. *
*
* @author Johan Ström
*/
public class ValueProvider {
private String prefix;
private Properties properties;
private PropertyMode propertyMode;
private StringListValueExtractor stringListValueExtractor;
private IntListValueExtractor intListValueExtractor;
private MapValueExtractor mapValueExtractor;
private StringValueExtractor stringValueExtractor;
private IntValueExtractor intValueExtractor;
private LongValueExtractor longValueExtractor;
private BooleanValueExtractor booleanValueExtractor;
private DoubleValueExtractor doubleValueExtractor;
private PropertiesListValueExtractor propertiesListValueExtractor;
private NestedValueExtractor nestedValueExtractor;
/**
* Initiates ValueProvider which is to work with data from the given properties.
*
* The PropertyMode controls which source(s) to consult, and in which order.
*
* @param prefix Only look at properties with this prefix.
* @param properties
* @param propertyMode Which source to prioritize
*/
public ValueProvider(String prefix, Properties properties, PropertyMode propertyMode) {
this.prefix = prefix;
this.properties = properties;
this.propertyMode = propertyMode;
stringListValueExtractor = new StringListValueExtractor();
intListValueExtractor = new IntListValueExtractor();
mapValueExtractor = new MapValueExtractor();
stringValueExtractor = new StringValueExtractor();
intValueExtractor = new IntValueExtractor();
longValueExtractor = new LongValueExtractor();
booleanValueExtractor = new BooleanValueExtractor();
doubleValueExtractor = new DoubleValueExtractor();
propertiesListValueExtractor = new PropertiesListValueExtractor();
nestedValueExtractor = new NestedValueExtractor();
}
public String getString(ConfigKey key, String fromConfig) {
return stringValueExtractor.getFromPreferredSource(prefix, key, fromConfig);
}
public Integer getInteger(ConfigKey key, Integer fromConfig) {
return intValueExtractor.getFromPreferredSource(prefix, key, fromConfig);
}
public int getInt(ConfigKey key, Integer fromConfig) {
Integer integer = getInteger(key, fromConfig);
if(integer == null) {
return 0;
}
return integer;
}
public Long getLong(ConfigKey key, Long fromConfig) {
return longValueExtractor.getFromPreferredSource(prefix, key, fromConfig);
}
public Boolean getBoolean(ConfigKey key, Boolean fromConfig) {
return booleanValueExtractor.getFromPreferredSource(prefix, key, fromConfig);
}
public List getList(ConfigKey key, List fromConfig) {
return stringListValueExtractor.getFromPreferredSource(prefix, key, fromConfig);
}
public List getIntList(ConfigKey key, List fromConfig) {
return intListValueExtractor.getFromPreferredSource(prefix, key, fromConfig);
}
public Map getMap(ConfigKey key, Map fromConfig) {
return mapValueExtractor.getFromPreferredSource(prefix, key, fromConfig);
}
public Double getDouble(ConfigKey key, Double fromConfig){
return doubleValueExtractor.getFromPreferredSource(prefix, key, fromConfig);
}
public List getPropertiesList(ConfigKey key, List fromConfig) {
return propertiesListValueExtractor.getFromPreferredSource(prefix, key, fromConfig);
}
public T getObject(ConfigKey key, T fromConfig, final com.google.common.base.Function converter) {
ValueExtractor arbitraryExtractor = new ValueExtractor() {
@Override
protected T withPrefix(String prefix, ConfigKey key, Properties properties) {
return converter.apply(properties.getProperty(key.asPropertyKey(prefix)));
}
};
return arbitraryExtractor.getFromPreferredSource(prefix, key, fromConfig);
}
public List getNestedList(ConfigKey key) {
List nested = nestedValueExtractor.getFromPreferredSource(prefix, key, null);
return nested == null ? Collections.emptyList() : nested;
}
/**
* Helper base class for picking values out of the Properties class and/or config value.
*
* If there is only one source defined, we only use that. If multiple source are defined, the first one has priority.
* If more than one value is specified, a merge policy as specified for the ConfigKey
*/
private abstract class ValueExtractor {
T getFromPreferredSource(String prefix, ConfigKey key, T fromConfig) {
if(propertyMode == PropertyMode.Skip) {
return fromConfig;
}
List values = new ArrayList<>();
// Find all non-null values, put into "values" with order based on the given propertyMode
T fromProperty = withPrefix(prefix, key, properties);
// Short-circuit
if(fromProperty == null && fromConfig == null) {
return null;
}
switch (propertyMode) {
case Only:
return fromProperty;
case Override:
if(fromProperty != null) {
values.add(fromProperty);
}
if(fromConfig != null) {
values.add(fromConfig);
}
break;
case Fallback:
if(fromConfig != null) {
values.add(fromConfig);
}
if(fromProperty != null) {
values.add(fromProperty);
}
break;
default:
throw new AssertionError("Invalid PropertyMode");
}
if(values.size() == 1) {
return values.get(0);
}
// values now has non-null values from both sources, in preference order.
// Let's merge according to the combine policy
ValueCombinePolicy combinePolicy = key.getValueCombinePolicy();
String overrideCombinePolicy = properties.getProperty(key.asPropertyKey(prefix) + "." + EnvUtil.PROPERTY_COMBINE_POLICY_SUFFIX);
if(overrideCombinePolicy != null) {
combinePolicy = ValueCombinePolicy.fromString(overrideCombinePolicy);
}
switch(combinePolicy) {
case Replace:
return values.get(0);
case Merge:
return merge(key, values);
}
return null;
}
/**
* Data type-specific extractor to read value from properties.
*
* @param prefix
* @param key
* @param properties
* @return
*/
protected abstract T withPrefix(String prefix, ConfigKey key, Properties properties);
protected T merge(ConfigKey key, List values) {
throw new IllegalArgumentException("Combine policy Merge is not available for "+key.asPropertyKey(prefix));
}
}
private class StringValueExtractor extends ValueExtractor {
@Override
protected String withPrefix(String prefix, ConfigKey key, Properties properties) {
return properties.getProperty(key.asPropertyKey(prefix));
}
}
private class IntValueExtractor extends ValueExtractor {
@Override
protected Integer withPrefix(String prefix, ConfigKey key, Properties properties) {
String prop = properties.getProperty(key.asPropertyKey(prefix));
return prop == null ? null : Integer.valueOf(prop);
}
}
private class LongValueExtractor extends ValueExtractor {
@Override
protected Long withPrefix(String prefix, ConfigKey key, Properties properties) {
String prop = properties.getProperty(key.asPropertyKey(prefix));
return prop == null ? null : Long.valueOf(prop);
}
}
private class BooleanValueExtractor extends ValueExtractor {
@Override
protected Boolean withPrefix(String prefix, ConfigKey key, Properties properties) {
String prop = properties.getProperty(key.asPropertyKey(prefix));
return prop == null ? null : Boolean.valueOf(prop);
}
}
private class DoubleValueExtractor extends ValueExtractor {
@Override
protected Double withPrefix(String prefix, ConfigKey key, Properties properties) {
String prop = properties.getProperty(key.asPropertyKey(prefix));
return prop == null ? null : Double.valueOf(prop);
}
}
private abstract class ListValueExtractor extends ValueExtractor> {
@Override
protected List withPrefix(String prefix, ConfigKey key, Properties properties) {
List strings = extractFromPropertiesAsList(key.asPropertyKey(prefix), properties);
if(strings == null) {
return null;
}
return process(strings);
}
protected abstract List process(List strings);
@Override
protected List merge(ConfigKey key, List> values) {
List merged = new ArrayList<>();
for (List value : values) {
merged.addAll(value);
}
return merged;
}
}
private class StringListValueExtractor extends ListValueExtractor {
@Override
protected List process(List strings) {
return strings;
}
}
private class IntListValueExtractor extends ListValueExtractor {
@Override
protected List process(List strings) {
List ints = new ArrayList<>();
for (String s : strings) {
ints.add(s != null ? Integer.parseInt(s) : 0);
}
return ints;
}
}
private class MapValueExtractor extends ValueExtractor
© 2015 - 2025 Weber Informatics LLC | Privacy Policy