This is an automated email from the ASF dual-hosted git repository.

anatole pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-tamaya-site.git

commit a461a094ea223bc98ac83a321b3079ea1bb8d386
Author: Anatole Tresch <[email protected]>
AuthorDate: Mon Dec 17 20:46:53 2018 +0100

    - Removed docs for PropertyValueCombinationPolicy+ (removed)
    - Added docs for ObjectValue,ListValue and snapshots (added)
---
 content/documentation/api.adoc  | 123 ++++++++++++++++++++++++++++++++--------
 content/documentation/core.adoc |   8 +--
 content/highleveldesign.adoc    |  24 +++-----
 3 files changed, 110 insertions(+), 45 deletions(-)

diff --git a/content/documentation/api.adoc b/content/documentation/api.adoc
index 6023724..c3b3c64 100644
--- a/content/documentation/api.adoc
+++ b/content/documentation/api.adoc
@@ -19,6 +19,7 @@ The API provides the artifacts as described in the 
link:../highleveldesign.html[
          a function +ConfigurationQuery<T>+.
   ** +Configuration+ also provides with +current()+ and +current(ClassLoader)+ 
static access point for
      obtaining the current configuration.
+  ** +ConfigurationSnapshot+ declares an immutable configuration instance, 
which supports consistent property access.
   ** +ConfigException+ defines a runtime exception for usage by the 
configuration system.
   ** +TypeLiteral+ provides a possibility to type safely define the target 
type to be returned in case non-String types
      are accessed. It is especially useful when accessing collections from 
Tamaya.
@@ -181,6 +182,10 @@ public interface Configuration{
     Configuration map(UnaryOperator<Configuration> operator);
     <T> T adapt(Function<Configuration,T> adapter);
 
+    // Snapshots for consistent config access
+    ConfigurationSnapshot getSnapshot(Iterable<String> keys);
+    ConfigurationSnapshot getSnapshot(String... keys);
+
     ConfigurationContext getContext();
     ConfigurationBuilder toBuilder();
     static Configuration current();
@@ -203,6 +208,12 @@ Hereby
 * +getOrDefault+ allows to pass default values as needed, returned if the 
requested value evaluated to +null+.
 * +getConfigurationContext()+ allows access to the underlying components of a 
+Configuration+ instance.
 * the +static+ methods allow access for obtaining or changing +Configuration+.
+* +getSnapshot+ allows to create a configuration snapshot, which guarantees 
consistent and immutable access to
+  a +Configuration+. It can optionally be constraint to a set of keys, by 
default a full snapshot is created.
+
+Accessor methods also support multi-key access, where an +Iterable+ of keys 
can be provided. This basically
+is equivalent to multiple calls to this method, where the result of the first 
successful call (returning
+configuration data) will end the evaluation chain.
 
 The class +TypeLiteral+ is basically similar to the same class provided with 
CDI:
 
@@ -238,7 +249,7 @@ singleton:
 [source,java]
 .Accessing Configuration
 --------------------------------------------
-Configuration config = ConfigurationProvider.getConfiguration();
+Configuration config = Configuration.current();
 --------------------------------------------
 
 Hereby the singleton is backed up by an instance of 
+ConfigurationProviderSpi+, which is managed by the
@@ -358,7 +369,6 @@ public final class PropertyValue implements Serializable{
     public PropertyValue setValue(String value);
     public Map<String, String> getMetaEntries();
     public String getMetaEntry(String key);
-    public PropertyValueBuilder toBuilder();
 
     public final PropertyValue getParent();
     public final int getVersion();
@@ -373,32 +383,67 @@ When writing your own datasource you can easily create 
your own +PropertyValues+
 
 [source,java]
 ----------------------------------------------------------------
-PropertyValue val = PropertyValue.of("key","value","source");
+PropertyValue val = PropertyValue.createValue("key","value");
+----------------------------------------------------------------
+
+You can also add additional metadata:
+
+[source,java]
+----------------------------------------------------------------
+val.addMetaEntry("figured", "true");
 ----------------------------------------------------------------
 
-If you want to add additional metadata in most cases you would use the builder 
API:
++PropertyValues+ are type safe value objects. To render a value
+immutable just call the corresponding method:
 
 [source,java]
 ----------------------------------------------------------------
-PropertyValue val = PropertyValue.builder("key","value","source")
-                     .addMetaEntry("figured", "true")
-                     .build();
+//mutable instance
+PropertyValue val = ...;
+
+// immutable instance
+PropertyValue newVal = val.immutable();
 ----------------------------------------------------------------
 
-+PropertyValues+ are type safe value objects. To change a value you have to 
create a
-new instance using a builder:
+Changing an immutable value will result in a +IllegalStateException+. The 
process also works the other way
+round, so an immutable instance can be rendered into a mutable as follows:
 
 [source,java]
 ----------------------------------------------------------------
-PropertyValue val = PropertyValue.builder("key","value","source")
-                     .addMetaEntry("figured", "true")
-                     .build();
-PropertyValue newVal = val.toBuilder().setValue("anotehrValue")
-                     .addMetaEntry("remote", "true")
-                     .removeMetaEntry("figured")
-                     .build();
+//immutable instance
+PropertyValue val = ...;
+
+// mutable instance
+PropertyValue newVal = val.mutable();
+----------------------------------------------------------------
+
+[[ObjectValue]]
+==== ObjectValue and ListValue
+
+In many cases using +PropertyValues+ is sufficient. Nevertheless when handling 
more complex configuration sources, such
+as file sources mapping hierarchical structures helps a lot. This is what 
+ObjectValue+ and +listValue+ are for:
+
+* +ObjectValue+ defines a +PropertyValue+ that has an arbitrary number of 
child values, identified by a unique text key.
+* +ListValue+ defines a +PropertyValue+ that has an arbitrary number of child 
values, organized as a list of
+  values.
+
+When rendered to +Map<String,String>+ generated keys look very familiar:
+
+[source,properties]
+----------------------------------------------------------------
+a.a=valA
+a.b=valB
+a.list[0]=val0
+a.list[1]=val1
+a.c=valC
 ----------------------------------------------------------------
 
+Hereby
+
+* +a+ can be mapped as an +ObjectValue+, with +a,b,c+ being normale 
+PropertyValue+ instances.
+* +list+ is also a child of +a+, but of type +ListValue+ containing two 
+PropertyValue+ instances.
+
+
 [[PropertySource]]
 === Interface PropertySource
 
@@ -416,11 +461,13 @@ identified to be necessary:
 [source,java]
 --------------------------------------------
 public interface PropertySource{
-      int getOrdinal();
+
+      default int getOrdinal();
       String getName();
       PropertyValue get(String key);
-      boolean isScannable();
       Map<String,PropertyValue> getProperties();
+
+      ...
 }
 --------------------------------------------
 
@@ -429,11 +476,6 @@ Hereby
 * +get+ looks similar to the methods on +Map+. It may return +null+ in case no 
such entry is available.
 * +getProperties+ allows to extract all property data to a 
+Map<String,PropertyValue>+. Other methods like +containsKey,
   keySet+ as well as streaming operations then can be applied on the returned 
+Map+ instance.
-* But not in all scenarios a property source is able to provide all values at 
once (aka to be _scannable_), e.g.
-  when looking up keys is very inefficient, it may not make sense to iterate 
over all keys to collect the corresponding
-  properties. If a +PropertySource+ is defined as non scannable accesses to
-  +getProperties()+ may not return all key/value pairs that would be available 
when accessed directly using the
-  +PropertyValue get(String)+ method. The fact if a +PropertySource+ is 
_scannable_ can be determined by calling +isScannable()+.
 * +int getOrdinal()+ defines the ordinal of the +PropertySource+. Property 
sources are managed in an ordered chain, where
   property sources with higher ordinals override ones with lower ordinals. If 
the ordinal of two property sources is
   the same, the natural ordering of the fully qualified class names of the 
property source implementations is used.
@@ -443,6 +485,11 @@ Hereby
   property sources.
 * Finally +getName()+ returns a (unique) name that identifies the 
+PropertySource+ within its containing +ConfigurationContext+.
 
+NOTE: Not in all scenarios a property source is able to provide all values at 
once, e.g.
+      when looking up keys is very inefficient. In this case
+      +getProperties()+ may not return all key/value pairs that would be 
available when accessed directly using the
+      +PropertyValue get(String)+ method.
+
 This interface can be implemented by any kind of logic. It could be a simple 
in memory map, a distributed configuration
 provided by a data grid, a database, the JNDI tree or other resources. Or it 
can be a combination of multiple
 property sources with additional combination/aggregation rules in place.
@@ -451,6 +498,34 @@ property sources with additional combination/aggregation 
rules in place.
 using the Java +ServiceLoader+ (or the mechanism provided by the current 
active +ServiceContext+, see later in this
 document for further details).
 
+==== Consistent Configuration Access
+
+For consistent configuration access using Snapshots property sources may 
provide additional services:
+
+[source,java]
+--------------------------------------------
+public interface PropertySource{
+
+      ...
+
+      // Method for consistent configuration access
+
+      default ChangeSupport getChangeSupport();
+      default String getVersion();
+      default void addChangeListener(BiConsumer<Set<String>, PropertySource> 
l);
+      default void removeChangeListener(BiConsumer<Set<String>, 
PropertySource> l);
+}
+--------------------------------------------
+
+These methods allow to determine Tamaya if all values accessed are consistent. 
The idea behind is that a
++PropertySource+ may change during a configuration evaluation. Providing a 
version allows the configuration system
+to detect such a change and restart the evaluation. Additionally registering 
of change listeners allow actively
+listening for changes. Since not all implementations may support versioning 
the may declare their capabilities:
+
+* +getChangeSupport()+ declares the versioning capabilities, possible values 
are +UNSUPPORTED,SUPPORTED,IMMUTABLE+.
+* +getVersion()+ returns a version. Returning a new String value signals c 
change in the property source.
+* +add/removeChangeListener+ allows to add or remove listeners.
+
 
 [[PropertySourceProvider]]
 === Interface PropertySourceProvider
@@ -459,7 +534,7 @@ Instances of this type can be used to register multiple 
instances of +PropertySo
 
 [source,java]
 --------------------------------------------
-// @FunctionalInterface in Java 8
+@FunctionalInterface
 public interface PropertySourceProvider{
     Collection<PropertySource> getPropertySources();
 }
diff --git a/content/documentation/core.adoc b/content/documentation/core.adoc
index a63e199..197a556 100644
--- a/content/documentation/core.adoc
+++ b/content/documentation/core.adoc
@@ -265,14 +265,10 @@ The default implementation +DefaultConfigValueEvaluator+ 
implements the followin
 
 . Collect all +PropertySources+ from the context.
 . Access +PropertyValue get(String)+ (single key access)/ 
+Map<String,PropertyValue> getProperties()+
-  (config map access) from each property source and combine the previous with 
the next value using
-  the +PropertyValueCombinationPolicy+ in place.
+  (config map access) from each property source and combines the previous with 
the next value.
 
 The resulting _raw_ value(s) are then finally handed over to the registered 
filters and finally
-converted to +String/Map<String,String>+ as required by the user API.
-
-To replace this default behaviour you must register your implementation with 
the current
-+ServiceContext+.
+converted to the target type as required by the user API.
 
 
 [[Extensions]]
diff --git a/content/highleveldesign.adoc b/content/highleveldesign.adoc
index d281aa9..54f26cc 100644
--- a/content/highleveldesign.adoc
+++ b/content/highleveldesign.adoc
@@ -80,10 +80,10 @@ PropertySources. Hereby the final value, by default, is 
determined by the last n
 +PropertySource+.
 
 Since the ladder may not always be appropriate, e.g. when values should be 
combined instead of overridden, a
-instance of +PropertyValueCombinationPolicy+ can be registered, which allows 
to add more detailed behaviour how values
-are combined.
+instance of +PropertyConverter+ actually has access to all values returned. 
This enables more complex value
+evaluation algorithms, when needed.
 
-Access to the complete configuration +Map+ is performing the same resolution 
and combination algorithm, but for all
+Access to the complete configuration +Map+ is performing the same resolution 
algorithm, but for all
 key/value pairs available.
 
 === Filtering the raw properties:
@@ -106,30 +106,23 @@ returned to the caller.
 Basically the bahaviour of Tamaya can be customized using the following 
mechanisms. Basically configuration can be
 provided using the following mechanism:
 
-* Registering additional (default) +PropertySource+ instances. Depending on 
their _ordinal value_ they
+* Registering additional +PropertySource+ instances. Depending on their 
_ordinal value_ they
   will override or extend existing configuration.
-* Registering additional (default) +PropertySourceProvider+ instances.that can 
provide multiple +PropertySource+
+* Registering additional +PropertySourceProvider+ instances, to provide 
multiple +PropertySource+
   instances.
 
 Additionally Tamaya provides hooks for further adapting the internal workings:
 
-* Adapting the way how multiple entries with the same key are combined 
(+PropertyValueCombinationPolicy+). This
-  may be useful, if overriding is not the way how entries of the same key 
should be combined. An example, where
-  such an alternate scenario is useful are list entries, that combine all 
entries encountered to a collecting
-  list entry.
 * Adding additional support for new target types configurable by registering 
additional +PropertyConverter+
   instances. This can be used for adding support for new types as well as for 
adding support for additional
   formats.
-* Complex extensions may adapt the complete +ConfigurationContext+, using the 
+ConfigurationContextBuilder+ and
-  reapply the changed instance using 
+ConfigurationProvider.setConfigurationContext(ConfigurationContext)+.
-  This is one example how to react on dynamic changes detected on 
configuration files read.
+* Complex extensions may adapt the complete +ConfigurationContext+.
 * Registering additional +PropertyFilter+ instances, that filter the 
configuration values extracted.
 * Registering an alternate +ServiceContext+ to support alternate runtime 
containers, e.g. a CDI container.
 * A combination of all above.
 
-Additionally instances of +ConfigOperator, ConfigQuery+ can be provided that 
provide additional functionality
-that should not be globally visible. It is recommended to provide them from a 
singleton accessor, hereby hiding
-the effective implementation classes.
+Additionally instances of +ConfigOperator, ConfigQuery+ can be implemented 
that provide additional functionality.
+
 
 == Component Loading
 
@@ -144,6 +137,7 @@ of the +ServiceContext+ interface, annotating it with a 
+@Priority+ annotation a
 
 The Tamaya API is compatible with Java 8 and beyond.
 
+
 == Further Documentation
 
 Being here we recommend to have a look at the more detailed documentation of 
Tamaya's link:documentation/api.html[API and SPI],

Reply via email to