http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java ---------------------------------------------------------------------- diff --git a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java index 5b61055..9f66b24 100644 --- a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java +++ b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java @@ -21,47 +21,53 @@ package org.apache.tamaya.spi; import java.io.Serializable; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; /** - * Class modelling the result of a request for a property value. A property value is basically identified by its key. - * There might be reasons, where one want to further analyze, which PropertySources provided a value and which not, so - * it is possible to create a PropertyValue with a null value. + * Class modelling the result of a request for a property createValue. A property createValue is basically identified by its key. + * There might be reasons, where one want to further analyze, which PropertySources provided a createValue and which not, so + * it is possible to createObject a PropertyValue with a null createValue. * * A PropertyValue represents an abstract data point in a configuration structure read. PropertyValues actually * represent a tree, with additional functionality for representing data lists/arrays using indexed children * names. This allows to support a full mapping of common document based configuration formats, such as JSON, YAML, * XML and more. */ -public final class PropertyValue implements Serializable, Iterable<PropertyValue>{ +public class PropertyValue implements Serializable, Iterable<PropertyValue>{ private static final long serialVersionUID = 1L; + /** The type of node. */ + private ValueType valueType; /** The requested key. */ private String key; - /** The value. */ + /** The createValue. */ private String value; - /** Additional metadata provided by the provider. */ - private final transient Map<String,Object> metaData = new HashMap<>(); - /** List of child properties. */ - private final List<PropertyValue> children = new ArrayList<>(); - /** The getParent getChild, null if it's a root getChild. */ + /** The getParent getField, null if it's a root getField. */ private PropertyValue parent; - /** The getChild's getIndex, if the getChild is participating in a list structure. */ - private int index = -1; - /** The value version, used for determining config changes. */ + /** The createValue version, used for determining config changes. */ private AtomicInteger version = new AtomicInteger(); - /** Helper structure used for indexing new list getChildren. */ - private Map<String, AtomicInteger> indices = new HashMap<>(); - /** Flag to mark a value as immutable. */ + /** Flag to mark a createValue as immutable. */ private boolean immutable; + /** Additional metadata provided by the provider. */ + private final transient Map<String,Object> metaData = new HashMap<>(); + /** + * Enum of the different supported value types. + */ + public enum ValueType{ + /** A multi valued property value, which contains named child properties. */ + OBJECT, + /** A multi valued property value, which contains unnamed child properties. */ + ARRAY, + /** A simple value property. */ + VALUE + } /** * Creates a new builder instance. * @param key the key, not {@code null}. * @param source the source, typically the name of the {@link PropertySource} - * providing the value, not {@code null}. + * providing the createValue, not {@code null}. * @return a new builder instance. * @deprecated Will be removed, use {@link PropertyValue} directly. */ @@ -74,78 +80,76 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue } /** - * Creates a new builder instance. - * @param key the key, not {@code null}. - * @param source the source. - * @return a new builder instance. - * @deprecated Use {@link #create(String)} + * Creates a new (invisible) root, which is a node with an empty name. + * @return a new empty root, never null. */ - @Deprecated - public static PropertyValue of(String key, String source){ - Objects.requireNonNull(key, "Key must be given."); + public static ObjectValue createObject(){ + return new ObjectValue(null, ""); + } - return new PropertyValue(null, key).setMeta("source", source); + /** + * Creates a new (invisible) root, which is a node with an empty name. + * @return a new empty root, never null. + */ + public static ListValue createList(){ + return new ListValue(null, ""); } /** - * Creates a new builder instance. + * Creates a new createValue of type {@link ValueType#VALUE}. * @param key the key, not {@code null}. - * @param value the property value, not {@code null}. - * @param source the source, typically the name of the {@link PropertySource} - * providing the value, not {@code null}. - * @return a new builder instance. + * @param value the createValue, not null. + * @return a new createValue instance. */ - @Deprecated - public static PropertyValue of(String key, String value, String source) { - Objects.requireNonNull(key, "Key must be given."); - if(source!=null) { - return new PropertyValue(null, key).setValue(value).setMeta("source", source); - } - return new PropertyValue(null, key).setValue(value); + public static PropertyValue createValue(String key, String value){ + return new PropertyValue(null, key, ValueType.VALUE, value); } /** - * Creates a new builder instance. + * Creates a new createValue of type {@link ValueType#ARRAY}. * @param key the key, not {@code null}. - * @param value the new value. - * @return a new builder instance. + * @return a new createValue instance. */ - public static PropertyValue create(String key, String value){ - Objects.requireNonNull(key, "Key must be given."); - - return new PropertyValue(null, key).setValue(value); + public static ListValue createList(String key){ + return new ListValue(null, key); } - /** - * Creates a new (invisible) root getChild, which is a getChild with an empty name. - * @return a new empty root getChild, never null. + * Creates a new createValue of type {@link ValueType#OBJECT}. + * @param key the key, not {@code null}. + * @return a new createValue instance. */ - public static PropertyValue create(){ - return new PropertyValue(null, ""); + public static ObjectValue createObject(String key){ + return new ObjectValue(null, key); } /** - * Creates a new named root getChild. - * @param name the name, not null. - * @return a new named root getChild, never null. + * Creates a new builder instance. + * @param key the key, not {@code null}. + * @param value the property createValue, not {@code null}. + * @param source the source, typically the name of the {@link PropertySource} + * providing the createValue, not {@code null}. + * @return a new builder instance. */ - public static PropertyValue create(String name){ - return new PropertyValue(null, name); + @Deprecated + public static PropertyValue of(String key, String value, String source) { + Objects.requireNonNull(key); + if(source!=null) { + return new PropertyValue(null, key, ValueType.VALUE, value).setMeta("source", source); + } + return new PropertyValue(null, key, ValueType.VALUE, value); } - - /** * Maps a map of {@code Map<String,String>} to a {@code Map<String,PropertyValue>}. * @param config the String based map, not {@code null}. * @param source the source name, not {@code null}. - * @return the corresponding value based map. + * @return the corresponding createValue based map. */ public static Map<String, PropertyValue> map(Map<String, String> config, String source) { Map<String, PropertyValue> result = new HashMap<>(config.size()); for(Map.Entry<String,String> en:config.entrySet()){ - result.put(en.getKey(), PropertyValue.of(en.getKey(), en.getValue(), source)); + result.put(en.getKey(), createValue(en.getKey(), en.getValue()).setMeta("source", source)); } return result; } @@ -156,7 +160,7 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue * @param config the String based map, not {@code null}. * @param source the source name, not {@code null}. * @param metaData additional metadata, not {@code null}. - * @return the corresponding value based map. + * @return the corresponding createValue based map. */ public static Map<String, PropertyValue> map(Map<String, String> config, String source, Map<String,String> metaData) { @@ -166,7 +170,7 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue Map<String, PropertyValue> result = new HashMap<>(config.size()); for(Map.Entry<String,String> en:config.entrySet()){ - PropertyValue pv = PropertyValue.create(en.getKey(), en.getValue()) + PropertyValue pv = createValue(en.getKey(), en.getValue()) .setMeta(metaData); if(source!=null){ pv.setMeta("source", source); @@ -179,17 +183,32 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue /** * Creates a new instance * @param key the key, not {@code null}. + * @param parent the parent. + * @param valueType the createValue type, not null. */ - private PropertyValue(PropertyValue parent, String key){ + protected PropertyValue(PropertyValue parent, String key, ValueType valueType){ + this(parent, key, valueType, null); + } + + /** + * Creates a new instance + * @param key the key, not {@code null}. + * @param parent the parent. + * @param valueType the createValue type, not null. + * @param value the initial text createValue. + */ + protected PropertyValue(PropertyValue parent, String key, ValueType valueType, String value){ this.parent = parent; - this.key = Objects.requireNonNull(key, "Key is required."); + this.valueType = Objects.requireNonNull(valueType, "ValueType is required."); + this.key = Objects.requireNonNull(key); + this.value = value; } /** * Checks if the instance is immutable. * @return true, if the instance is immutable. */ - public boolean isImmutable(){ + public final boolean isImmutable(){ return immutable; } @@ -198,28 +217,70 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue * an {@link IllegalStateException}. * @return this instance for chaining. */ - public PropertyValue setImmutable(){ + public PropertyValue immutable(){ this.immutable = true; - children.forEach(PropertyValue::setImmutable); return this; } /** + * Clones this instance and all it's children, marking as mutable createValue. + * @return the new createValue clone. + */ + public PropertyValue mutable(){ + if(!immutable){ + return this; + } + return deepClone(); + } + + /** + * Get the item's current createValue type. + * @return the createValue type, never null. + */ + public final ValueType getValueType() { + return valueType; + } + + /** * The requested key. * @return the, key never {@code null}. */ - public String getKey() { + public final String getKey() { return key; } /** - * Get a qualified name of a getChild in property format using '.' as separator, e.g. + * Get the node's createValue. + * @return the createValue, or null. + */ + public String getValue() { + return this.value; + } + + /** + * Sets the createValue. + * @param value the createValue + * @return this getField for chaining. + * @throws IllegalStateException if the instance is immutable. + * @see #isImmutable() + */ + public PropertyValue setValue(String value) { + checkImmutable(); + if(!Objects.equals(this.value, value)) { + this.value = value; + incrementVersion(); + } + return this; + } + + /** + * Get a qualified name of a getField in property format using '.' as separator, e.g. * {@code a.b.c} or {@code a.b.c[0]} for indexed entries. Entries hereby also can have multiple * levels of indexing, e.g. {@code a[1].b.c[14].d} is a valid option. * * The qualified key is defined by {@link #getQualifiedKey()} of it's parent concatenated with the key * of this node. If there is no parent, or the parent's qualified key is empty only {@link #getKey()} - * is returned. Additionally if the current values is an indeyed value the key is extended by the + * is returned. Additionally if the current values is an indeyed createValue the key is extended by the * index in brackets, e.g. {@code [0], [1], ...}. All the subsequent keys are valid qualified keys: * <pre> * a @@ -236,29 +297,21 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue return key; } String parentName = parent.getQualifiedKey(); - if(!parentName.isEmpty()){ - parentName+="."; - } - if(isIndexed()){ - return parentName+key+"["+index+"]"; + if(parent instanceof ListValue){ + return parentName+"["+((ListValue)parent).getIndex(this)+"]"; + }else{ + if(!parentName.isEmpty()){ + parentName+="."; + } + return parentName+key; } - return parentName+key; } /** - * The value. - * @return the value, in case a value is null it is valid to return {#code null} as result for - * {@link PropertySource#get(String)}. - */ - public String getValue() { - return this.value; - } - - /** - * Get the getChild's getParent. + * Get the getField's getParent. * @return the getParent, or null. */ - public PropertyValue getParent(){ + public final PropertyValue getParent(){ return parent; } @@ -266,83 +319,64 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue * Get the values version, the version is updated with each change written. * @return the version. */ - public int getVersion(){ + public final int getVersion(){ return version.get(); } /** - * Get a getChild's getIndex. - * @return the getIndex, or -1, if the getChild does not participate in an array. - */ - public int getIndex(){ - return index; - } - - /** * Get the source. * @return the source, or null. * @deprecated Use {@code getMeta("source")}. */ @Deprecated - public String getSource() { + public final String getSource() { return (String)this.metaData.get("source"); } /** - * Checks if the getChild is a root getChild. - * @return true, if the current getChild is a root getChild. + * Checks if the getField is a root getField. + * @return true, if the current getField is a root getField. */ - public boolean isRoot() { + public final boolean isRoot() { return parent == null; } /** - * Checks if the getChild is a leaf getChild (has no getChildren). - * @return true, if the current getChild is a leaf getChild. - */ - public boolean isLeaf(){ - return children.isEmpty(); - } - - /** - * Allows to check if a getChild is indexed. - * @return true, if the getChild participates in an array. + * Checks if the getField is a leaf getField (has no getList). + * @return true, if the current getField is a leaf getField. */ - public boolean isIndexed(){ - if(parent==null){ - return false; - } - return index>=0; + public final boolean isLeaf(){ + return getValueType()==ValueType.VALUE; } /** - * Creates a full configuration map for this key, value pair and all its getMeta context data. This map - * is also used for subsequent processing, like value filtering. - * @return the property value entry map. + * Creates a full configuration map for this key, createValue pair and all its getMeta context data. This map + * is also used for subsequent processing, like createValue filtering. + * @return the property createValue entry map. */ - public Map<String, Object> getMeta() { + public final Map<String, Object> getMeta() { return Collections.unmodifiableMap(metaData); } /** - * Access the given key from this value. Valid keys are the key or any getMeta-context key. + * Access the given key from this createValue. Valid keys are the key or any getMeta-context key. * @param key the key, not {@code null}. - * @return the value found, or {@code null}. + * @return the createValue found, or {@code null}. * @deprecated Use {@link #getMeta(String)} instead of. */ @Deprecated - public String getMetaEntry(String key) { + public final String getMetaEntry(String key) { return (String)this.metaData.get(Objects.requireNonNull(key)); } /** - * Access the given key from this value. Valid keys are the key or any getMeta-context key. + * Access the given key from this createValue. Valid keys are the key or any getMeta-context key. * @param key the key, not {@code null}. * @param <T> the target type. - * @return the value found, or {@code null}. + * @return the createValue found, or {@code null}. */ - public <T> T getMeta(String key) { + public final <T> T getMeta(String key) { return (T)this.metaData.get(Objects.requireNonNull(key)); } @@ -350,216 +384,26 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue * Access the given metadata. * @param type the type, not {@code null}. * @param <T> the target type. - * @return the value found, or {@code null}. + * @return the createValue found, or {@code null}. */ - public <T> T getMeta(Class<T> type) { + public final <T> T getMeta(Class<T> type) { return (T)this.metaData.get(type.getName()); } - /** - * Get a single child getChild by name. - * @param name the child's name, not null. - * @return the child found, or null. - * @throws IllegalArgumentException if multiple getChildren with the given name are existing (ambigous). - */ - public PropertyValue getChild(String name){ - List<PropertyValue> nodes = this.getChildren(name); - if(nodes.isEmpty()){ - return null; - } - if(nodes.size()>1){ - throw new IllegalArgumentException("Multiple getChildren existing: " + name); - } - return nodes.get(0); - } - - /** - * Get a sub value. - * @param index the target getIndex. - * @return the value found. - * @throws java.util.NoSuchElementException if no such element is existing. - */ - public PropertyValue getChild(int index) { - return this.children.get(index); - } - - /** - * Get a single child getChild with the given name, creates it if not existing. - * @param name the child's name, not null. - * @return the child found or created, never null. - * @throws IllegalArgumentException if multiple getChildren with the given name are existing (ambigous). - * @throws IllegalStateException if the instance is immutable. - * @see #isImmutable() - */ - public PropertyValue getOrCreateChild(String name){ - List<PropertyValue> nodes = this.getChildren(name); - if(nodes.isEmpty()){ - checkImmutable(); - PropertyValue n = new PropertyValue(this, name); - this.children.add(n); - version.incrementAndGet(); - return n; - } - if(nodes.size()>1){ - throw new IllegalArgumentException("Multiple getChildren existing: " + name); - } - return nodes.get(0); - } - - /** - * Get's the n-th getChild of an indexed getChild setCurrent. - * @param name the child's name, not null. - * @param index the target getChild getIndex. - * @return the getChild found, or null. - */ - public PropertyValue getChildWithIndex(String name, int index){ - List<PropertyValue> nodes = this.getChildren(name); - if(nodes.isEmpty() || nodes.size()<=index){ - return null; - } - return nodes.get(index); - } /** - * Get all child getChildren with a given name. - * @param name the target name, not null. - * @return the list of matching getChildren, could be none, one or multiple in case of arrays. + * Get the createValue's number of elements. + * @return the getNumChilds of this multi createValue. */ - public List<PropertyValue> getChildren(String name){ - return children.stream().filter(n -> n.key.equals(name)).collect(Collectors.toList()); - } - - /** - * Get the value's number of elements. - * @return the getNumChilds of this multi value. - */ - public int getNumChilds() { - return this.children.size(); - } - - /** - * The value. - * @return the value, in case a value is null it is valid to return {#code null} as result for - * {@link PropertySource#get(String)}. - */ - public List<PropertyValue> getChildren() { - return Collections.unmodifiableList(this.children); + public int getSize() { + return 0; } @Override public Iterator<PropertyValue> iterator() { - return Collections.unmodifiableList(this.children).iterator(); - } - - /** - * Adds a new non-indexed child getChild. - * @param name the child's name, not null. - * @return the new child, never null. - * @throws IllegalStateException if the instance is immutable. - * @see #isImmutable() - */ - public PropertyValue createChild(String name){ - return createChild(name, false); - } - - /** - * Adds a new non-indexed child. - * @param name the child's name, not null. - * @param value the child's value, not null. - * @return the new child, not null. - * @throws IllegalStateException if the instance is immutable. - * @see #isImmutable() - */ - public PropertyValue createChild(String name, String value){ - return createChild(name, false).setValue(value); - } - - /** - * Adds another existing node, hereby setting the corresponding parent node. - * @param value the value, not null - * @return this instance, for chaining. - * @throws IllegalStateException if the instance is immutable. - * @see #isImmutable() - */ - public PropertyValue addChild(PropertyValue value) { - checkImmutable(); - value.parent = this; - this.children.add(value); - return this; - } - - /** - * Adds a new child getChild. - * @param name the child's name, not null. - * @param indexed if true, the getChild will be participate in an array of the given name. - * @return the new getChild, not null. - * @throws IllegalStateException if the instance is immutable. - * @see #isImmutable() - */ - public PropertyValue createChild(String name, boolean indexed){ - checkImmutable(); - PropertyValue n = new PropertyValue(this, name); - this.children.add(n); - version.incrementAndGet(); - if(indexed) { - AtomicInteger index = indices.computeIfAbsent(name, s -> new AtomicInteger(0)); - n.index = index.getAndIncrement(); - }else{ - List<PropertyValue> nodes = this.getChildren(name); - if(nodes.size()>1){ - AtomicInteger index = indices.get(name); - if(index!=null){ - n.index = index.getAndIncrement(); - }else{ - index = new AtomicInteger(0); - indices.put(name, index); - for(PropertyValue node:nodes){ - node.index = index.getAndIncrement(); - } - } - } - } - return n; - } - - /** - * Adds a new child getChild, where the getChild is given in '.'-separated property notation, - * e.g. {@code a.b.c}. - * @param key the property key, e.g. {@code a.b.c} - * @param value the property value - * @return the new leaf-getChild created. - * @throws IllegalStateException if the instance is immutable. - * @see #isImmutable() - */ - public PropertyValue addProperty(String key, String value) { - checkImmutable(); - PropertyValue node = this; - StringTokenizer tokenizer = new StringTokenizer(key, "\\.", false); - while(tokenizer.hasMoreTokens()){ - String token = tokenizer.nextToken().trim(); - node = node.getOrCreateChild(token); - if(!tokenizer.hasMoreTokens()){ - // Its the last or single token - node.setValue(value); - } - } - return node; + return Collections.emptyIterator(); } - /** - * Adds multiple child getChildren, where the getChildren are defined in '.'-separated property notation, - * * e.g. {@code a.b.c}. - * @param props the properties - * @return the collection of added leaf-child getChildren. - * @throws IllegalStateException if the instance is immutable. - * @see #isImmutable() - */ - public Collection<PropertyValue> addProperties(Map<String,String> props) { - checkImmutable(); - List<PropertyValue> result = new ArrayList<>(); - props.entrySet().forEach(en -> result.add(addProperty(en.getKey(), en.getValue()))); - return result; - } /** * Changes the entry's key, mapping also corresponding context entries. @@ -577,21 +421,6 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue return this; } - /** - * Sets the value. - * @param value the value - * @return this getChild for chaining. - * @throws IllegalStateException if the instance is immutable. - * @see #isImmutable() - */ - public PropertyValue setValue(String value) { - checkImmutable(); - if(!Objects.equals(this.value, value)) { - this.value = value; - version.incrementAndGet(); - } - return this; - } /** * Replaces/sets the context data. @@ -600,7 +429,7 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue * @throws IllegalStateException if the instance is immutable. * @see #isImmutable() */ - public PropertyValue setMeta(Map<String, Object> metaEntries) { + public final PropertyValue setMeta(Map<String, Object> metaEntries) { checkImmutable(); if(!Objects.equals(this.metaData, metaEntries)) { this.metaData.clear(); @@ -613,15 +442,15 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue /** * Add an additional context data information. * @param key the context data key, not {@code null}. - * @param value the context value, not {@code null} (will be converted to String). + * @param value the context createValue, not {@code null} (will be converted to String). * @return the builder for chaining. * @throws IllegalStateException if the instance is immutable. * @see #isImmutable() */ - public PropertyValue setMeta(String key, Object value) { + public final PropertyValue setMeta(String key, Object value) { checkImmutable(); Objects.requireNonNull(key, "Meta key must be given."); - Objects.requireNonNull(value, "Meta value must be given."); + Objects.requireNonNull(value, "Meta createValue must be given."); if(!Objects.equals(this.metaData.get(key), value)) { this.metaData.put(key, value); version.incrementAndGet(); @@ -632,16 +461,16 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue /** * Add an additional context data information. * @param type the context data type, used as key, not {@code null}. - * @param value the context value, not {@code null}. + * @param value the context createValue, not {@code null}. * @param <T> the target type. * @return the builder for chaining. * @throws IllegalStateException if the instance is immutable. * @see #isImmutable() */ - public <T> PropertyValue setMeta(Class<T> type, T value) { + public final <T> PropertyValue setMeta(Class<T> type, T value) { checkImmutable(); Objects.requireNonNull(type, "Meta key must be given."); - Objects.requireNonNull(value, "Meta value must be given."); + Objects.requireNonNull(value, "Meta createValue must be given."); if(!Objects.equals(this.metaData.get(type.toString()), value)) { this.metaData.put(type.toString(), value); version.incrementAndGet(); @@ -651,15 +480,15 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue /** * Add an additional context data information, using the data's class name as key. - * @param value the context value, not {@code null}. + * @param value the context createValue, not {@code null}. * @param <T> the target type. * @return the builder for chaining. * @throws IllegalStateException if the instance is immutable. * @see #isImmutable() */ - public <T> PropertyValue setMeta(T value) { + public final <T> PropertyValue setMeta(T value) { checkImmutable(); - Objects.requireNonNull(value, "Meta value must be given."); + Objects.requireNonNull(value, "Meta createValue must be given."); if(!Objects.equals(this.metaData.get(value.getClass().toString()), value)) { this.metaData.put(value.getClass().toString(), value); version.incrementAndGet(); @@ -674,7 +503,7 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue * @throws IllegalStateException if the instance is immutable. * @see #isImmutable() */ - public PropertyValue removeMeta(String key) { + public final PropertyValue removeMeta(String key) { checkImmutable(); Objects.requireNonNull(key, "Key must be given."); if(this.metaData.containsKey(key)) { @@ -691,7 +520,7 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue * @throws IllegalStateException if the instance is immutable. * @see #isImmutable() */ - public PropertyValue removeMeta(Class type) { + public final PropertyValue removeMeta(Class type) { checkImmutable(); Objects.requireNonNull(key, "Key must be given."); if(this.metaData.containsKey(type.getName())) { @@ -702,17 +531,14 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue } /** - * Convert the getChild tree to a property map. + * Convert the getField tree to a property map. * @return the corresponding property map, not null. */ - public Map<String,String> asMap(){ + public Map<String,String> toMap(){ Map<String, String> map = new TreeMap<>(); - if(isLeaf()){ + if(value!=null) { map.put(getQualifiedKey(), value); } - for(PropertyValue n: children){ - map.putAll(n.asMap()); - } return map; } @@ -721,7 +547,7 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue * @return the corresponding String representation, not null. */ public String asString() { - Map<String, String> map = asMap(); + Map<String, String> map = toMap(); StringBuilder b = new StringBuilder(); map.entrySet().forEach(en -> b.append(en.getKey()).append(" = ").append(en.getValue()).append('\n')); if(b.length()==0){ @@ -741,36 +567,45 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue .setMeta(this.metaData); } - /** - * Clones this instance and all it's children, marking as mutable value. - * @return the new value clone. - */ - public PropertyValue mutable(){ - if(!immutable){ - return this; - } - PropertyValue newProp = new PropertyValue(this.parent, key); - newProp.setValue(this.value); - newProp.setMeta(metaData); - children.forEach(c -> newProp.children.add(c.mutable())); - newProp.version = new AtomicInteger(version.intValue()); + public PropertyValue toPropertyValue(){ + return this; + } + + public ObjectValue toObjectValue(){ + ObjectValue ov = new ObjectValue(getParent(),getKey()); + ov.setField("createValue", value); + return ov; + } + + public ListValue toListValue(){ + ListValue lv = new ListValue(getParent(),getKey()); + lv.addValue("createValue", value); + return lv; + } + + + protected PropertyValue deepClone() { + PropertyValue newProp = new PropertyValue(getParent(), getKey(), ValueType.VALUE, this.value); + newProp.setMeta(getMeta()); + newProp.setVersion(getVersion()); return newProp; } + @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof PropertyValue)) return false; PropertyValue dataNode = (PropertyValue) o; - return Objects.equals(parent, dataNode.parent) && - Objects.equals(key, dataNode.key) && + return getParent() == dataNode.getParent() && + Objects.equals(getKey(), dataNode.getKey()) && Objects.equals(value, dataNode.value) && - Objects.equals(metaData, dataNode.metaData); + Objects.equals(getMeta(), dataNode.getMeta()); } @Override public int hashCode() { - return Objects.hash(parent, key, value, metaData); + return Objects.hash(getParent(), getKey(), value, getMeta()); } @@ -778,16 +613,29 @@ public final class PropertyValue implements Serializable, Iterable<PropertyValue public String toString() { return "PropertyValue{" + '\'' +getQualifiedKey() + '\'' + - (value!=null?", value='" + value + '\'':"") + - ", children='" + children.size() + '\'' + - (metaData.isEmpty()?"":", metaData=" + metaData) + + (value!=null?", createValue='" + value + '\'':"") + + (getMeta().isEmpty()?"":", metaData=" + getMeta()) + '}'; } - private void checkImmutable(){ + protected final void checkImmutable(){ if(immutable){ throw new IllegalStateException("Instance is immutable."); } } + protected final int incrementVersion(){ + checkImmutable(); + return version.incrementAndGet(); + } + + protected final void setVersion(int version) { + this.version.set(version); + } + + protected final void setParent(PropertyValue parent){ + this.parent = parent; + } + + }
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java ---------------------------------------------------------------------- diff --git a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java index 20f49a0..57bd058 100644 --- a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java +++ b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java @@ -22,24 +22,24 @@ import java.util.*; import java.util.concurrent.atomic.AtomicInteger; /** - * Builder to create a {@link org.apache.tamaya.spi.PropertyValue} instance. + * Builder to createObject a {@link org.apache.tamaya.spi.PropertyValue} instance. * @deprecated Use {@link PropertyValue} directly. */ @Deprecated public final class PropertyValueBuilder { /** The key accessed. */ protected String key; - /** The property value. */ + /** The property createValue. */ protected String value; - /** The property value. */ + /** The property createValue. */ protected String source; /** additional metadata entries (optional). */ protected Map<String,Object> metaEntries = new HashMap<>(); - /** The getParent getChild, null if it's a root getChild. */ + /** The getParent getField, null if it's a root getField. */ protected PropertyValue parent; - /** The getChild's getIndex, if the getChild is participating in a list structure. */ + /** The getField's getIndex, if the getField is participating in a createList structure. */ protected int index = -1; - /** Helper structure used for indexing new list getChildren. */ + /** Helper structure used for indexing new createList getList. */ protected Map<String, AtomicInteger> indices = new HashMap<>(); /** @@ -66,12 +66,12 @@ public final class PropertyValueBuilder { /** * Add an additional context data information. * @param key the context data key, not {@code null}. - * @param value the context value, not {@code null} (will be converted to String). + * @param value the context createValue, not {@code null} (will be converted to String). * @return the builder for chaining. */ public PropertyValueBuilder addMetaEntry(String key, Object value) { Objects.requireNonNull(key, "Meta key must be given."); - Objects.requireNonNull(value, "Meta value must be given."); + Objects.requireNonNull(value, "Meta createValue must be given."); this.metaEntries.put(key, value); return this; @@ -80,13 +80,13 @@ public final class PropertyValueBuilder { /** * Add an additional context data information. * @param type the context data type, used as key, not {@code null}. - * @param value the context value, not {@code null}. + * @param value the context createValue, not {@code null}. * @param <T> the type of the class modeled by the type parameter * @return the builder for chaining. */ public <T> PropertyValueBuilder addMetaEntry(Class<T> type, T value) { Objects.requireNonNull(type, "Meta key must be given."); - Objects.requireNonNull(value, "Meta value must be given."); + Objects.requireNonNull(value, "Meta createValue must be given."); this.metaEntries.put(type.toString(), value); return this; @@ -94,12 +94,12 @@ public final class PropertyValueBuilder { /** * Add an additional context data information, using the data's class name as key. - * @param value the context value, not {@code null}. + * @param value the context createValue, not {@code null}. * @param <T> the type of the class modeled by the type parameter * @return the builder for chaining. */ public <T> PropertyValueBuilder addMetaEntry(T value) { - Objects.requireNonNull(value, "Meta value must be given."); + Objects.requireNonNull(value, "Meta createValue must be given."); this.metaEntries.put(value.getClass().toString(), value); return this; @@ -128,7 +128,7 @@ public final class PropertyValueBuilder { } /** - * Get the value's context data. + * Get the createValue's context data. * @return the context data, not {@code null}. */ public Map<String,Object> getMetaEntries() { @@ -136,7 +136,7 @@ public final class PropertyValueBuilder { } /** - * Get the value's context data. + * Get the createValue's context data. * @param <T> the type of the class modeled by the type parameter * @return the context data, not {@code null}. */ @@ -145,7 +145,7 @@ public final class PropertyValueBuilder { } /** - * Get the value's context data. + * Get the createValue's context data. * @param <T> the type of the class modeled by the type parameter * @param type the target type, not null. * @return the context data, not {@code null}. @@ -185,8 +185,8 @@ public final class PropertyValueBuilder { } /** - * Sets a new value. - * @param value the new value, not {@code null}. + * Sets a new createValue. + * @param value the new createValue, not {@code null}. * @return the builder for chaining. */ public PropertyValueBuilder setValue(String value) { @@ -221,7 +221,7 @@ public final class PropertyValueBuilder { public String toString() { return "PropertyValueBuilder{" + "key='" + key + '\'' + - ", value='" + value + '\'' + + ", createValue='" + value + '\'' + ", source='" + source + '\'' + ", metaEntries=" + metaEntries + '}'; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java ---------------------------------------------------------------------- diff --git a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java index 10a3200..59f0f7a 100644 --- a/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java +++ b/code/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java @@ -21,7 +21,7 @@ package org.apache.tamaya.spi; /** - * Policy that determines how the final value of a configuration entry is evaluated. An instances of this + * Policy that determines how the final createValue of a configuration entry is evaluated. An instances of this * interface can be registered to current control how multiple PropertySources are combined. This is useful in cases * where the default overriding policy as implemented in {@link #DEFAULT_OVERRIDING_POLICY} is not matching * the need of the current application, e.g. then entries containing multiple values should be combined to new @@ -52,22 +52,22 @@ public interface PropertyValueCombinationPolicy { /** - * Method that is called for each value evaluated by a PropertySource for the given key. This method is called + * Method that is called for each createValue evaluated by a PropertySource for the given key. This method is called * either when a single key is accessed, e.g. by calling {@code org.apache.tamaya.Configuration.getXXX}, but also * when the full configuration property map is accessed by calling * {@link org.apache.tamaya.Configuration#getProperties()}. * - * @param currentValue the current value, including metadata entries. If no such key is present the current value + * @param currentValue the current createValue, including metadata entries. If no such key is present the current createValue * is null. - * The collector should either combine the existing value with value from {@code currentValue} - * or replace the value in {@code currentValue} with {@code valueRead}, hereby returning the + * The collector should either combine the existing createValue with createValue from {@code currentValue} + * or replace the createValue in {@code currentValue} with {@code valueRead}, hereby returning the * result to be used as new {@code currentValue}. * @param key The current key to be evaluated. - * @param propertySource The PropertySource that may return an value for the given key. The PropertySource given + * @param propertySource The PropertySource that may return an createValue for the given key. The PropertySource given * may be evaluated for additional getMeta-data, how the given values are to be combined. - * Note that the value returned by a PropertySource can be null. In that case + * Note that the createValue returned by a PropertySource can be null. In that case * {@code currentValue} should be returned in almost all cases. - * @return the value to be used for future evaluation, including metadata entries. + * @return the createValue to be used for future evaluation, including metadata entries. */ PropertyValue collect(PropertyValue currentValue, String key, PropertySource propertySource); http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java ---------------------------------------------------------------------- diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java b/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java index c9a521f..0576196 100644 --- a/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java +++ b/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.net.URL; import java.text.MessageFormat; import java.util.*; +import java.util.function.Supplier; import java.util.logging.Level; @@ -43,7 +44,7 @@ public interface ServiceContext extends ClassloaderAware{ } /** - * Checks the given instance for a @Priority annotation. If present the annotation's value is evaluated. If no such + * Checks the given instance for a @Priority annotation. If present the annotation's createValue is evaluated. If no such * annotation is present, a default priority of {@code 1} is returned. * @param o the instance, not {@code null}. * @return a priority, by default 1. @@ -68,11 +69,26 @@ public interface ServiceContext extends ClassloaderAware{ * @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority. */ default <T> T getService(Class<T> serviceType){ - return create(serviceType); + return getService(serviceType, null); } /** - * Factory method to create a type, hereby a new instance is created on each access. + * Access a service singleton via its type. + * If multiple implementations for the very serviceType exist then + * the one with the highest {@link javax.annotation.Priority} will be used. + * + * @param <T> the type of the service type. + * @param serviceType the service type. + * @param supplier the supplier to be used, if no services could be evaluated. If null, + * an empty collection is returned, when no services + * could be located. + * @return The instance to be used, or {@code null} + * @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority. + */ + <T> T getService(Class<T> serviceType, Supplier<T> supplier); + + /** + * Factory method to createObject a type, hereby a new instance is created on each access. * If multiple implementations for the very serviceType exist then * the one with the highest {@link javax.annotation.Priority} will be used as the base * for creating subsequent instances. @@ -82,29 +98,53 @@ public interface ServiceContext extends ClassloaderAware{ * @return The new instance to be used, or {@code null} * @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority. */ - default <T> T create(Class<T> serviceType){ - @SuppressWarnings("unchecked") - Class<? extends T> implType = null; - Collection<T> services = getServices(serviceType); - if (services.isEmpty()) { - return null; - } else { - return ((List<T>) services).get(0); - } + default <T> T create(Class<T> serviceType){ + return create(serviceType, null); } + /** + * Factory method to createObject a type, hereby a new instance is created on each access. + * If multiple implementations for the very serviceType exist then + * the one with the highest {@link javax.annotation.Priority} will be used as the base + * for creating subsequent instances. + * + * @param <T> the type of the service type. + * @param serviceType the service type. + * @return The new instance to be used, or {@code null} + * @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority. + */ + <T> T create(Class<T> serviceType, Supplier<T> supplier); /** - * Access a list current services, given its type. The bootstrap mechanism should + * Access a createList current services, given its type. The bootstrap mechanism should * order the instance for precedence, hereby the most significant should be * first in order. * * @param serviceType * the service type. - * @param <T> the type of the list element returned by this method + * @param <T> the type of the createList element returned by this method * @return The instance to be used, never {@code null} */ - <T> List<T> getServices(Class<T> serviceType); + default <T> List<T> getServices(Class<T> serviceType){ + return getServices(serviceType, null); + } + + /** + * Access a createList current services, given its type. The bootstrap mechanism should + * order the instance for precedence, hereby the most significant should be + * first in order. If no instances could be found, the instances supplied by the + * supplier given are registered and used. + * + * @param serviceType + * the service type. + * @param <T> the type of the createList element returned by this method + * @param supplier the supplier to be used, if no services could be evaluated. If null, + * an empty collection is returned, when no services + * could be located. + * @return The instance to be used, never {@code null} + */ + <T> List<T> getServices(Class<T> serviceType, Supplier<List<T>> supplier); + /** * Loads resources from the current runtime context. This method allows to use runtime * specific code to load resources, e.g. within OSGI environments. @@ -126,4 +166,26 @@ public interface ServiceContext extends ClassloaderAware{ return getClassLoader().getResource(resource); } + /** + * Registers the given instance as a singleton service for the given instance, if no + * instance already has been registered. + * + * @param type the type to register, not null. + * @param instance the instance, not null. + * @param <T> thy type. + * @param force if true, any existing instance will be replaced. + * @return the instance registered or already present. + */ + <T> T register(Class<T> type, T instance, boolean force); + + /** + * Registers the given instancea as servicea for the given instance, if no + * * instance already has been registered. + * @param type the type to register, not null. + * @param instances the instancea, not null. + * @param <T> thy type. + * @param force if true, any existing instances will be replaced. + * @return the instances registered or already present. + */ + <T> List<T> register(Class<T> type, List<T> instances, boolean force); } http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java ---------------------------------------------------------------------- diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java b/code/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java index 3c008d1..9909a40 100644 --- a/code/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java +++ b/code/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java @@ -109,6 +109,7 @@ public final class ServiceContextManager { * @return the {@link ServiceContext} used. */ public static ServiceContext getServiceContext(ClassLoader classLoader) { + Objects.requireNonNull(classLoader, "Classloader required."); return serviceContexts.computeIfAbsent(classLoader, ServiceContextManager::loadDefaultServiceProvider); } http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/ConfigurationProviderTest.java ---------------------------------------------------------------------- diff --git a/code/api/src/test/java/org/apache/tamaya/ConfigurationProviderTest.java b/code/api/src/test/java/org/apache/tamaya/ConfigurationProviderTest.java index 521c7cd..787e04f 100644 --- a/code/api/src/test/java/org/apache/tamaya/ConfigurationProviderTest.java +++ b/code/api/src/test/java/org/apache/tamaya/ConfigurationProviderTest.java @@ -29,7 +29,7 @@ import org.mockito.Mockito; * * Test the {@link ConfigurationProivder} class. The tests end up being tests of * the default methods in the {@link ConfigurationProivder} interface as they - * pass through to the {@link TestConfigurationProvider} mocked object. + * pass through to the {@link TestConfigurationProvider} mocked createObject. */ public class ConfigurationProviderTest { http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java ---------------------------------------------------------------------- diff --git a/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java b/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java index 94923ff..bb68697 100644 --- a/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java +++ b/code/api/src/test/java/org/apache/tamaya/TestConfiguration.java @@ -100,7 +100,7 @@ public class TestConfiguration implements Configuration { @Override public Map<String, String> getProperties() { - // run toString on each value of the (key, value) setCurrent in VALUES + // run toString on each createValue of the (key, createValue) setCurrent in VALUES return VALUES.entrySet().stream().collect( Collectors.toMap( Map.Entry::getKey, http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationProviderSpiTest.java ---------------------------------------------------------------------- diff --git a/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationProviderSpiTest.java b/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationProviderSpiTest.java index fb8e7b3..067a18a 100644 --- a/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationProviderSpiTest.java +++ b/code/api/src/test/java/org/apache/tamaya/spi/ConfigurationProviderSpiTest.java @@ -49,7 +49,7 @@ TestConfigurationProvider configProvider = new TestConfigurationProvider(); try{ configProvider.setConfigurationContext(newContext); //The mocked TestConfigurationProvider doesn't setCurrent the context on the - // inner Configuration object, as that's deprecated. + // inner Configuration createObject, as that's deprecated. assertThat(configProvider.getConfigurationContext()).isEqualTo(newContext); }finally{ configProvider.setConfigurationContext(currentContext); http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java ---------------------------------------------------------------------- diff --git a/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java b/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java index 35842ca..3ed57f3 100644 --- a/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java +++ b/code/api/src/test/java/org/apache/tamaya/spi/FilterContextTest.java @@ -115,7 +115,7 @@ public class FilterContextTest { public void getConfigEntries() throws Exception { Map<String,PropertyValue> config = new HashMap<>(); for(int i=0;i<10;i++) { - config.put("key-"+i, PropertyValue.of("key-"+i, "value-"+i, "test")); + config.put("key-"+i, PropertyValue.of("key-"+i, "createValue-"+i, "test")); } PropertyValue val = PropertyValue.of("getConfigEntries", "v", ""); FilterContext ctx = new FilterContext(val, config, ConfigurationContext.EMPTY); @@ -127,7 +127,7 @@ public class FilterContextTest { public void testToString() throws Exception { Map<String,PropertyValue> config = new HashMap<>(); for(int i=0;i<2;i++) { - config.put("key-"+i, PropertyValue.of("key-"+i, "value-"+i, "test")); + config.put("key-"+i, PropertyValue.of("key-"+i, "createValue-"+i, "test")); } PropertyValue val = PropertyValue.of("testToString", "val", "mySource"); FilterContext ctx = new FilterContext(val, config, ConfigurationContext.EMPTY); @@ -135,8 +135,8 @@ public class FilterContextTest { assertThat(toString).isNotNull(); System.out.println(toString); - assertThat(toString.contains("FilterContext{value='[PropertyValue{'testToString', value='val', children='0', " + - "metaData={source=mySource}}]', configEntries=[")).isTrue(); + assertThat(toString.contains("FilterContext{createValue='[PropertyValue{'testToString', createValue='val'," + + " metaData={source=mySource}}]', configEntries=[")).isTrue(); assertThat(toString.contains("key-0")).isTrue(); assertThat(toString.contains("key-1")).isTrue(); assertThat(toString.endsWith("}")).isTrue(); http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueBuilderTest.java ---------------------------------------------------------------------- diff --git a/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueBuilderTest.java b/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueBuilderTest.java index d0d8874..fef0712 100644 --- a/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueBuilderTest.java +++ b/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueBuilderTest.java @@ -150,7 +150,7 @@ // PropertyValueBuilder b = new PropertyValueBuilder("k", "v").setSource("testSetContextData"); // Map<String,String> context = new HashMap<>(); // context.put("source", "testSetContextData"); -// context.put("ts", String.valueOf(System.currentTimeMillis())); +// context.put("ts", String.createValue(System.currentTimeMillis())); // context.put("y", "yValue"); // b.setMeta(new HashMap<String, String>()); // b.setMeta(context); @@ -177,13 +177,13 @@ // // @Test // public void testMapKey() { -// PropertyValueBuilder b = new PropertyValueBuilder("key", "value") +// PropertyValueBuilder b = new PropertyValueBuilder("key", "createValue") // .setMeta("_keyAndThenSome", "mappedvalue") // .setMeta("somethingelse", "othervalue") // .mapKey("mappedkey"); // PropertyValue pv = b.build(); // Assertions.assertThat(pv.getKey()).isEqualTo("mappedkey"); -// Assertions.assertThat(pv.getValue()).isEqualTo("value"); +// Assertions.assertThat(pv.getValue()).isEqualTo("createValue"); // Assertions.assertThat(pv.getMeta()).hasSize(2); // assertThat(pv.getMeta("_mappedkey.AndThenSome")).isEqualTo("mappedvalue"); // assertThat(pv.getMeta("somethingelse")).isEqualTo("othervalue"); @@ -194,7 +194,7 @@ // PropertyValueBuilder b = new PropertyValueBuilder("k", "v") // .setMeta("metak", "metav"); // System.out.println(b.toString()); -// assertThat(b.toString()).isEqualTo("PropertyValueBuilder{key='k'value='v'listValue='[]', metaEntries={metak=metav}}"); +// assertThat(b.toString()).isEqualTo("PropertyValueBuilder{key='k'createValue='v'listValue='[]', metaEntries={metak=metav}}"); // } // // @Test(expected = NullPointerException.class) http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java ---------------------------------------------------------------------- diff --git a/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java b/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java index 3a9d3ef..0ebfbcc 100644 --- a/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java +++ b/code/api/src/test/java/org/apache/tamaya/spi/PropertyValueTest.java @@ -22,7 +22,6 @@ import org.assertj.core.api.Assertions; import org.junit.Test; import java.util.HashMap; -import java.util.List; import java.util.Map; import static org.assertj.core.api.Assertions.*; @@ -60,7 +59,7 @@ public class PropertyValueTest { @Test(expected = NullPointerException.class) public void testSetMetaEntriesRequiresNonNullParameter() { - PropertyValue.create().setMeta(null); + PropertyValue.createObject().setMeta(null); } @Test @@ -68,7 +67,7 @@ public class PropertyValueTest { Map<String,Object> meta = new HashMap<>(); meta.put("1","2"); meta.put("a", "b"); - PropertyValue pv = PropertyValue.create() + PropertyValue pv = PropertyValue.createObject() .setMeta("k", "v2") .setMeta(meta); assertThat(pv.getMeta().get("k")).isNull(); @@ -79,18 +78,18 @@ public class PropertyValueTest { @Test(expected = NullPointerException.class) public void removeMetaEntryRequiresNonNullParameter() { - PropertyValue.create().removeMeta((String)null); + PropertyValue.createObject().removeMeta((String)null); } @Test(expected = NullPointerException.class) public void removeMetaEntryRequiresNonNullParameterClass() { - PropertyValue.create().removeMeta((Class)null); + PropertyValue.createObject().removeMeta((Class)null); } @Test public void testRemoveMetaEntry() throws Exception { - PropertyValue pv = PropertyValue.create("k") + PropertyValue pv = PropertyValue.createObject("k") .setMeta("k", "v2") .setMeta("k2", "v22") .removeMeta("k"); @@ -100,7 +99,7 @@ public class PropertyValueTest { @Test public void testRemoveMetaEntryClass() throws Exception { - PropertyValue pv = PropertyValue.create("k") + PropertyValue pv = PropertyValue.createObject("k") .setMeta(String.class, "v2") .setMeta("k2", "v22") .removeMeta(String.class); @@ -113,7 +112,7 @@ public class PropertyValueTest { Map<String,Object> meta = new HashMap<>(); meta.put("1","2"); meta.put("a", "b"); - PropertyValue pv = PropertyValue.create("k") + PropertyValue pv = PropertyValue.createObject("k") .setMeta(meta); assertThat(pv.getMeta()).isEqualTo(meta); Assertions.assertThat(pv.getMeta()).isEqualTo(meta); @@ -164,110 +163,88 @@ public class PropertyValueTest { @Test public void testGetMetaEntry() throws Exception { - PropertyValue pv = PropertyValue.create("k") - .setValue("v") + PropertyValue pv = PropertyValue.createObject("k") .setMeta("k", "v2"); - Assertions.assertThat(pv.getValue()).isEqualTo("v"); Assertions.assertThat(pv.getKey()).isEqualTo("k"); assertThat(pv.getMeta().get("k")).isEqualTo("v2"); - assertThat((String)pv.getMeta("k")).isEqualTo("v2"); } @Test(expected = NullPointerException.class) public void testInstantiateNoKey1() throws Exception { - PropertyValue.create((String)null); + PropertyValue.createObject((String)null); } @Test(expected = NullPointerException.class) public void testInstantiateNoKey2() throws Exception { - PropertyValue.of(null, "v", "testGetKey"); + PropertyValue.createValue(null, "v"); } @Test public void testInstantiateNoValue2() throws Exception { - PropertyValue.of("k", null, "testGetKey"); + PropertyValue.createValue("k", null); } @Test public void testInstantiateNoSource2() throws Exception { - PropertyValue.of("k", "v", null); + PropertyValue.createValue("k", "v"); } @Test(expected = NullPointerException.class) public void addMetaEntryRequiresNonNullParameterForKey() { - PropertyValue.create("k").setMeta((String)null, "a"); + PropertyValue.createObject("k").setMeta((String)null, "a"); } @Test(expected = NullPointerException.class) public void addMetaEntryRequiresNonNullParameterForKeyClass() { - PropertyValue.create("k").setMeta((Class)null, "a"); + PropertyValue.createValue("k", null).setMeta((Class)null, "a"); } @Test(expected = NullPointerException.class) public void addMetaEntryRequiresNonNullParameterForValue() { - PropertyValue.create("k").setMeta("a", null); + PropertyValue.createObject("k").setMeta("a", null); } @Test - public void setValueRequiresNullParameterForValue() { - PropertyValue.create("k").setValue(null); + public void newXXX() { + assertNotNull(PropertyValue.createValue("", null)); + assertNotNull(PropertyValue.createObject()); + assertNotNull(PropertyValue.createObject("")); + assertNotNull(PropertyValue.createList()); + assertNotNull(PropertyValue.createList("")); } @Test - public void create() { - assertNotNull(PropertyValue.create()); - assertTrue(PropertyValue.create().isRoot()); - PropertyValue n = PropertyValue.create().getOrCreateChild("child"); - assertFalse(n.isRoot()); - } - - @Test - public void create_String() { - PropertyValue foo = PropertyValue.create("foo"); + public void valueOf() { + PropertyValue foo = PropertyValue.createValue("foo", "bar"); assertNotNull(foo); assertEquals("foo", foo.getKey()); - PropertyValue n = PropertyValue.create("bar").getOrCreateChild("child"); - assertFalse(n.isRoot()); - } - - @Test - public void getOrCreateChild() { - PropertyValue root = PropertyValue.create("bar"); - assertTrue(root.getChildren().isEmpty()); - assertNotNull(root.getOrCreateChild("foo")); - assertFalse(root.getChildren().isEmpty()); - assertFalse(root.getChildren("foo").isEmpty()); - assertTrue(root.getOrCreateChild("foo") == root.getOrCreateChild("foo")); - assertTrue(root.getChildren("bar").isEmpty()); - assertTrue(root.getOrCreateChild("bar") == root.getOrCreateChild("bar")); - assertFalse(root.getChildren("bar").isEmpty()); + assertEquals("bar", foo.getValue()); } @Test - public void getChild() { - PropertyValue root = PropertyValue.create("bar"); - assertNull(root.getChild("foo")); - root.getOrCreateChild("foo"); - assertNotNull(root.getChild("foo")); + public void arrayOf() { + ListValue foo = PropertyValue.createList("foo"); + assertNotNull(foo); + assertEquals("foo", foo.getKey()); } @Test - public void createChild_Indexed() { - PropertyValue root = PropertyValue.create("a"); - assertNotNull(root.createChild("a", true)); - List<PropertyValue> nodes = root.getChildren("a"); - assertEquals(1, nodes.size()); - assertTrue(root.createChild("a").isIndexed()); - nodes = root.getChildren("a"); - assertEquals(2, nodes.size()); - assertFalse(root.createChild("b").isIndexed()); - assertTrue(root.createChild("b").isIndexed()); + public void objectOf() { + ObjectValue root = PropertyValue.createObject("bar"); + assertTrue(root.getSize() == 0); + assertNotNull(root.setField("foo", null)); + assertFalse(root.getSize()==0); + assertNotNull(root.getField("foo")); + assertNull(root.getField("foo").getValue()); + assertNotNull(root.setField("foo", "bar")); + assertEquals(root.getField("foo").getValue(), "bar"); + assertTrue(root.getSize()==1); } @Test public void addMeta() { - PropertyValue root = PropertyValue.create(); + PropertyValue root = PropertyValue.createObject(); assertNotNull(root.setMeta("a")); root.setMeta("a", Integer.valueOf(3)); assertEquals(Integer.valueOf(3), root.getMeta("a")); @@ -275,91 +252,81 @@ public class PropertyValueTest { @Test public void getKey() { - PropertyValue root = PropertyValue.create("a"); + PropertyValue root = PropertyValue.createObject("a"); assertEquals("a", root.getKey()); } @Test public void getQualifiedKey() { - PropertyValue root = PropertyValue.create("a"); + ObjectValue root = PropertyValue.createObject("a"); assertEquals("a", root.getQualifiedKey()); - PropertyValue n = root.createChild("b"); - assertEquals("a.b", n.getQualifiedKey()); - PropertyValue added = n.createChild("c"); + ObjectValue child = PropertyValue.createObject("b"); + ObjectValue n = root.set(child); + assertEquals("a.b", child.getQualifiedKey()); + PropertyValue added = child.setField("c", null); assertEquals("a.b.c", added.getQualifiedKey()); - added = n.createChild("c"); - assertEquals("a.b.c[1]", added.getQualifiedKey()); - assertEquals("a.b.c[0]", n.getChildWithIndex("c",0).getQualifiedKey()); - } - - @Test - public void isIndexed() { - PropertyValue n = PropertyValue.create(); - assertFalse(n.isIndexed()); - assertFalse(n.createChild("a").isIndexed()); - assertFalse(n.createChild("b").isIndexed()); - assertFalse(n.createChild("c").isIndexed()); - assertTrue(n.createChild("c").isIndexed()); } @Test public void isLeaf() { - PropertyValue n = PropertyValue.create(); + PropertyValue n = PropertyValue.createValue("", ""); assertTrue(n.isLeaf()); - n.createChild("b"); + n = PropertyValue.createList(""); assertFalse(n.isLeaf()); } @Test public void getParent() { - PropertyValue n = PropertyValue.create(); + ObjectValue n = PropertyValue.createObject(""); assertNull(n.getParent()); - n = n.createChild("b"); - assertNotNull(n.getParent()); - } - - @Test - public void getChildren_Filtered() { - PropertyValue n = PropertyValue.create(); - n.createChild("a"); - n.createChild("b"); - n.createChild("c"); - n.createChild("c"); - List<PropertyValue> nodes = n.getChildren("a"); - assertNotNull(nodes); - assertEquals(1, nodes.size()); - assertEquals("a", nodes.get(0).getKey()); - - nodes = n.getChildren("c"); - assertEquals(2, nodes.size()); - assertEquals("c", nodes.get(0).getKey()); - assertEquals("c", nodes.get(1).getKey()); - } - - @Test - public void getChildren() { - PropertyValue n = PropertyValue.create(); - n.createChild("a"); - n.createChild("b"); - n.createChild("c"); - n.createChild("c"); - List<PropertyValue> nodes = n.getChildren(); - assertNotNull(nodes); - assertEquals(4, nodes.size()); - assertEquals("a", nodes.get(0).getKey()); - assertEquals("b", nodes.get(1).getKey()); - assertEquals("c", nodes.get(2).getKey()); - assertEquals("c", nodes.get(3).getKey()); - } + n.setFieldObject("b"); + assertNotNull(n.getField("b")); + assertNotNull(n.getField("b").getParent()); + } + +// @Test +// public void getChildren_Filtered() { +// PropertyValue n = PropertyValue.createObject(); +// n.setField("a"); +// n.setField("b"); +// n.setField("c"); +// n.setField("c"); +// List<PropertyValue> nodes = n.getList("a"); +// assertNotNull(nodes); +// assertEquals(1, nodes.size()); +// assertEquals("a", nodes.getField(0).getKey()); +// +// nodes = n.getList("c"); +// assertEquals(2, nodes.size()); +// assertEquals("c", nodes.getField(0).getKey()); +// assertEquals("c", nodes.getField(1).getKey()); +// } +// +// @Test +// public void getList() { +// PropertyValue n = PropertyValue.createObject(); +// n.setField("a"); +// n.setField("b"); +// n.setField("c"); +// n.setField("c"); +// List<PropertyValue> nodes = n.getList(); +// assertNotNull(nodes); +// assertEquals(4, nodes.size()); +// assertEquals("a", nodes.getField(0).getKey()); +// assertEquals("b", nodes.getField(1).getKey()); +// assertEquals("c", nodes.getField(2).getKey()); +// assertEquals("c", nodes.getField(3).getKey()); +// } @Test public void asMap() { - PropertyValue n = PropertyValue.create(); - n.createChild("a", "aVal"); - n.createChild("b").createChild("b2").createChild("b3", "b3Val"); - n.createChild("c", "cVal1"); - n.createChild("c", "cVal2"); - Map<String,String> map = n.asMap(); + ObjectValue n = PropertyValue.createObject(""); + n.setField("a", "aVal"); + n.setFieldObject("b").setFieldObject("b2").setField("b3", "b3Val"); + ListValue array = n.setFieldList("c"); + array.addValue("cVal1"); + array.addValue("cVal2"); + Map<String,String> map = n.toMap(); System.out.println(map); assertEquals(4, map.size()); assertEquals("aVal", map.get("a")); @@ -370,34 +337,31 @@ public class PropertyValueTest { @Test public void asString() { - PropertyValue n = PropertyValue.create(); - n.createChild("a", "aVal"); - n.createChild("b").createChild("b2").createChild("b3", "b3Val"); - n.createChild("c", "cVal1"); - n.createChild("c", "cVal2"); + ObjectValue n = PropertyValue.createObject(); + n.setField("a", "aVal"); + n.setField("b.b2.b3", "b3Val"); + n.setField("c", "cVal2"); assertEquals("a = aVal\n" + "b.b2.b3 = b3Val\n" + - "c[0] = cVal1\n" + - "c[1] = cVal2\n", n.asString()); + "c = cVal2\n", n.asString()); } @Test public void equals() { - assertEquals(PropertyValue.create(), PropertyValue.create()); - assertNotEquals(PropertyValue.create("a"), PropertyValue.create()); - assertEquals(PropertyValue.create("b"), PropertyValue.create("b")); - PropertyValue root = PropertyValue.create(); + assertEquals(PropertyValue.createObject(), PropertyValue.createObject()); + assertNotEquals(PropertyValue.createObject("a"), PropertyValue.createObject()); + assertEquals(PropertyValue.createObject(""), PropertyValue.createObject()); + PropertyValue root = PropertyValue.createObject(); assertEquals(root, root); } @Test public void testToString() { - PropertyValue n = PropertyValue.create(); - n.createChild("a", "aVal"); - n.createChild("b").createChild("b2").createChild("b3", "b3Val"); - n.createChild("c", "cVal1"); - n.createChild("c", "cVal2"); - assertEquals("PropertyValue{'', children='4'}", n.toString()); + ObjectValue n = PropertyValue.createObject(""); + n.setField("a", "aVal"); + n.setField("b.b2.b3", "b3Val"); + n.setFieldList("c").addValue("cVal1"); + assertEquals("PropertyValue[OBJECT]{'', size='3'}", n.toString()); } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java ---------------------------------------------------------------------- diff --git a/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java b/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java index 90218aa..77f0e85 100644 --- a/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java +++ b/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java @@ -25,6 +25,7 @@ import java.net.URL; import java.util.Collections; import java.util.Enumeration; import java.util.List; +import java.util.function.Supplier; import static org.assertj.core.api.Assertions.*; @@ -72,17 +73,17 @@ public class ServiceContextManagerTest { } @Override - public <T> T getService(Class<T> serviceType) { + public <T> T getService(Class<T> serviceType, Supplier<T> supplier) { return null; } @Override - public <T> T create(Class<T> serviceType) { + public <T> T create(Class<T> serviceType, Supplier<T> supplier) { return null; } @Override - public <T> List<T> getServices(Class<T> serviceType) { + public <T> List<T> getServices(Class<T> serviceType, Supplier<List<T>> supplier) { return Collections.emptyList(); } @@ -95,6 +96,16 @@ public class ServiceContextManagerTest { public URL getResource(String resource) { return null; } + + @Override + public <T> T register(Class<T> type, T instance, boolean force) { + return instance; + } + + @Override + public <T> List<T> register(Class<T> type, List<T> instancea, boolean force) { + return instancea; + } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java ---------------------------------------------------------------------- diff --git a/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java b/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java index 65db2af..afa33bc 100644 --- a/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java +++ b/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java @@ -23,6 +23,7 @@ import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.net.URL; import java.util.*; +import java.util.function.Supplier; import org.junit.Test; @@ -46,7 +47,7 @@ public class ServiceContextTest { } @Override - public <T> T getService(Class<T> serviceType) { + public <T> T getService(Class<T> serviceType, Supplier<T> supplier) { if(String.class.equals(serviceType)){ return serviceType.cast("ServiceContextTest"); } @@ -54,13 +55,12 @@ public class ServiceContextTest { } @Override - public <T> T create(Class<T> serviceType) { + public <T> T create(Class<T> serviceType, Supplier<T> supplier) { return getService(serviceType); } - @SuppressWarnings("unchecked") - @Override - public <T> List<T> getServices(Class<T> serviceType) { + @Override + public <T> List<T> getServices(Class<T> serviceType, Supplier<List<T>> supplier) { if(String.class.equals(serviceType)){ List<String> list = new ArrayList<>(); list.add("ServiceContextTest"); @@ -69,6 +69,16 @@ public class ServiceContextTest { return Collections.emptyList(); } + @Override + public <T> T register(Class<T> type, T instance, boolean force) { + return instance; + } + + @Override + public <T> List<T> register(Class<T> type, List<T> instances, boolean force) { + return instances; + } + }; @Test http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/TestLowerOrdinalServiceContext.java ---------------------------------------------------------------------- diff --git a/code/api/src/test/java/org/apache/tamaya/spi/TestLowerOrdinalServiceContext.java b/code/api/src/test/java/org/apache/tamaya/spi/TestLowerOrdinalServiceContext.java index 24f3fe4..b7f2991 100644 --- a/code/api/src/test/java/org/apache/tamaya/spi/TestLowerOrdinalServiceContext.java +++ b/code/api/src/test/java/org/apache/tamaya/spi/TestLowerOrdinalServiceContext.java @@ -21,6 +21,7 @@ package org.apache.tamaya.spi; import java.io.IOException; import java.net.URL; import java.util.*; +import java.util.function.Supplier; /** * This class implements the (default) @@ -51,16 +52,31 @@ public final class TestLowerOrdinalServiceContext implements ServiceContext { } @Override + public <T> T getService(Class<T> serviceType, Supplier<T> supplier) { + return null; + } + + @Override public <T> T create(Class<T> serviceType) { throw ex; } @Override + public <T> T create(Class<T> serviceType, Supplier<T> supplier) { + throw ex; + } + + @Override public <T> List<T> getServices(Class<T> serviceType) { throw ex; } @Override + public <T> List<T> getServices(Class<T> serviceType, Supplier<List<T>> supplier) { + throw ex; + } + + @Override public Enumeration<URL> getResources(String resource) throws IOException { throw ex; } @@ -70,4 +86,14 @@ public final class TestLowerOrdinalServiceContext implements ServiceContext { throw ex; } + @Override + public <T> T register(Class<T> type, T instance, boolean force) { + throw ex; + } + + @Override + public <T> List<T> register(Class<T> type, List<T> instancea, boolean force) { + throw ex; + } + } http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/67ffcbf2/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java ---------------------------------------------------------------------- diff --git a/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java b/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java index 805e07c..9aae439 100644 --- a/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java +++ b/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.net.URL; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.Logger; @@ -57,12 +58,11 @@ public final class TestServiceContext implements ServiceContext { return 5; } - @SuppressWarnings("rawtypes") - @Override - public <T> T getService(Class<T> serviceType) { + @Override + public <T> T getService(Class<T> serviceType, Supplier<T> supplier) { T cached = serviceType.cast(singletons.get(serviceType)); if(cached==null) { - cached = create(serviceType); + cached = create(serviceType, supplier); singletons.put((Class)serviceType, cached); } if (cached == Object.class) { @@ -71,42 +71,45 @@ public final class TestServiceContext implements ServiceContext { return cached; } - @SuppressWarnings("unchecked") - @Override - public <T> T create(Class<T> serviceType) { - Collection<T> services = getServices(serviceType); - if (services.isEmpty()) { - return (T) Object.class; // as marker for 'nothing here' - } - else{ - return services.iterator().next(); + @Override + public <T> T create(Class<T> serviceType, Supplier<T> supplier) { + try { + for (T t : ServiceLoader.load(serviceType)) { + return t; + } + }catch(Exception e){ + if(supplier!=null) { + T instance = supplier.get(); + if(instance instanceof ClassloaderAware){ + ((ClassloaderAware)instance).init(this.classLoader); + } + return instance; + } + throw new IllegalArgumentException("Failed to instantiate instance:"); } + return null; } - /** - * Loads and registers services. - * - * @param <T> the concrete type. - * - * @param serviceType The service type. - * @return the items found, never {@code null}. - */ @Override - public <T> List<T> getServices(Class<T> serviceType) { + public <T> List<T> getServices(Class<T> serviceType, Supplier<List<T>> supplier) { + List<T> services; try { - List<T> services = new ArrayList<>(); + services = new ArrayList<>(); for (T t : ServiceLoader.load(serviceType)) { services.add(t); } services = Collections.unmodifiableList(services); - @SuppressWarnings("unchecked") - final List<T> previousServices = List.class.cast(servicesLoaded.putIfAbsent(serviceType, (List<Object>)services)); - return previousServices != null ? previousServices : services; } catch (Exception e) { - Logger.getLogger(TestServiceContext.class.getName()).log(Level.WARNING, - "Error loading services current type " + serviceType, e); - return Collections.emptyList(); + if(supplier==null){ + Logger.getLogger(TestServiceContext.class.getName()).log(Level.WARNING, + "Error loading services current type " + serviceType, e); + return Collections.emptyList(); + } + services = Collections.unmodifiableList(supplier.get()); } + @SuppressWarnings("unchecked") + final List<T> previousServices = List.class.cast(servicesLoaded.putIfAbsent(serviceType, (List<Object>)services)); + return previousServices != null ? previousServices : services; } @Override @@ -119,4 +122,24 @@ public final class TestServiceContext implements ServiceContext { return classLoader.getResource(resource); } + @Override + public <T> T register(Class<T> type, T instance, boolean force) { + if(force){ + servicesLoaded.put(type, Collections.singletonList(instance)); + }else{ + servicesLoaded.putIfAbsent(type, Collections.singletonList(instance)); + } + return (T)servicesLoaded.get(type).get(0); + } + + @Override + public <T> List<T> register(Class<T> type, List<T> instances, boolean force) { + if(force){ + servicesLoaded.put(type, Collections.singletonList(instances)); + }else { + servicesLoaded.putIfAbsent(type, Collections.singletonList(instances)); + } + return (List<T>)servicesLoaded.get(type); + } + }
