Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 5E588200C4B for ; Mon, 6 Mar 2017 00:29:33 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 5CDB6160B87; Sun, 5 Mar 2017 23:29:33 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 838B5160B6B for ; Mon, 6 Mar 2017 00:29:32 +0100 (CET) Received: (qmail 8982 invoked by uid 500); 5 Mar 2017 23:29:31 -0000 Mailing-List: contact commits-help@tamaya.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@tamaya.incubator.apache.org Delivered-To: mailing list commits@tamaya.incubator.apache.org Received: (qmail 8973 invoked by uid 99); 5 Mar 2017 23:29:31 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd4-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 05 Mar 2017 23:29:31 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd4-us-west.apache.org (ASF Mail Server at spamd4-us-west.apache.org) with ESMTP id 58D61C2112 for ; Sun, 5 Mar 2017 23:29:31 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd4-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -6.567 X-Spam-Level: X-Spam-Status: No, score=-6.567 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-2.999, SPF_NEUTRAL=0.652] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd4-us-west.apache.org [10.40.0.11]) (amavisd-new, port 10024) with ESMTP id CUUhDSrAYoO5 for ; Sun, 5 Mar 2017 23:29:29 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 18DD45FDD9 for ; Sun, 5 Mar 2017 23:29:27 +0000 (UTC) Received: (qmail 8964 invoked by uid 99); 5 Mar 2017 23:29:27 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 05 Mar 2017 23:29:27 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 473B7DFDE4; Sun, 5 Mar 2017 23:29:27 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: anatole@apache.org To: commits@tamaya.incubator.apache.org Date: Sun, 05 Mar 2017 23:29:28 -0000 Message-Id: <00cf923e5d2f4ce781170af47ddca60f@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [2/2] incubator-tamaya-site git commit: TAMAYA-252: Unified PropertyValue builder API. archived-at: Sun, 05 Mar 2017 23:29:33 -0000 TAMAYA-252: Unified PropertyValue builder API. Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/commit/a449f485 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/tree/a449f485 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/diff/a449f485 Branch: refs/heads/master Commit: a449f485a057e7ef05c911f0333463dec40b8e60 Parents: b400321 Author: anatole Authored: Mon Mar 6 00:28:58 2017 +0100 Committer: anatole Committed: Mon Mar 6 00:28:58 2017 +0100 ---------------------------------------------------------------------- content/documentation/api.adoc | 99 ++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya-site/blob/a449f485/content/documentation/api.adoc ---------------------------------------------------------------------- diff --git a/content/documentation/api.adoc b/content/documentation/api.adoc index ffd8850..9e133fe 100644 --- a/content/documentation/api.adoc +++ b/content/documentation/api.adoc @@ -31,9 +31,10 @@ The API provides the artifacts as described in the link:../highleveldesign.html[ the configuration data provided is managed locally, remotedely. There is even no requirement that the configuration data is always fully available. Summarizing a +PropertySource+ - *** provides String based property access for single key/value pairs in _raw_ format (meaning no postprocessing - is applied yet). - *** can _optionally_ provide access to a +Iterable+, providing all its properties at once. + *** provides property access for single key/value pairs in _raw_ format (meaning no postprocessing + is applied yet). A single property hereby is modelled as +PropertyValue+, which also includes + its source and additional arbitrary metadata entries. + *** can _optionally_ provide access to a +Map+, providing all its properties at once. *** defines the default ordinal to be used for establishing the order of significance among all auto-discovered property sources. ** _PropertySourceProvider:_ allows to automatically register multiple property sources, e.g. all config files found in @@ -278,6 +279,88 @@ The class +ConfigException+ models the base *runtime* exception used by the conf [[SPI]] == SPI +[[PropertyValue]] +=== PropertyValue, PropertyValueBuilder + +On the API properties are represented as Strings only, whereas in the SPI value are represented as +ProeprtyValue+, +which contain + +* the property's _key_ (String) +* the property's _value_ (String) +* the property's _source_ (String, typically equals to the property source's name) +* any additional meta-data represented as _Map_ + +This helps to kepp all value relevant data together in one place and also allows to choose any kind of +representation for meta-data entries. The +PropertyValue+ itself is a final and _serializable_ data container, +which also has a powerful builder API (e.g. for using within filters): + +[source,java] +---------------------------------------------------------------- +public final class PropertyValue implements Serializable{ + [...] + + public static PropertyValue of(String key, String value, String source); + + public String getKey(); + public String getSource(); + public String getValue(); + public Map getMetaEntries(); + public String getMetaEntry(String key); + public PropertyValueBuilder toBuilder(); + + public static PropertyValueBuilder builder(String key, String source); + public static PropertyValueBuilder builder(String key, String value, String source); + + /** + * Maps a map of {@code Map} to a {@code Map}. + * @param config the String based map, not null. + * @param source the source name, not null. + * @return the corresponding value based map. + */ + public static Map map(Map config, String source); + + /** + * Maps a map of {@code Map} to a {@code Map}. + * @param config the String based map, not null. + * @param source the source name, not null. + * @param metaData additional metadata, not null. + * @return the corresponding value based map. + */ + public static Map map(Map config, String source, + Map metaData); +} +---------------------------------------------------------------- + +When writing your own datasource you can easily create your own +PropertyValues+: + +[source,java] +---------------------------------------------------------------- +PropertyValue val = PropertyValue.of("key","value","source"); +---------------------------------------------------------------- + +If you want to add additional metadata in most cases you would use the builder API: + +[source,java] +---------------------------------------------------------------- +PropertyValue val = PropertyValue.builder("key","value","source") + .addMetaEntry("figured", "true") + .build(); +---------------------------------------------------------------- + ++PropertyValues+ are type safe value objects. To change a value you have to create a +new instance using a builder: + +[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(); +---------------------------------------------------------------- + [[PropertySource]] === Interface PropertySource @@ -299,20 +382,20 @@ public interface PropertySource{ String getName(); PropertyValue get(String key); boolean isScannable(); - Iterable getProperties(); + Map getProperties(); } -------------------------------------------- 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+. Other methods like +containsKey, +* +getProperties+ allows to extract all property data to a +Map+. 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 - +String get(String)+ method. The fact if a +PropertySource+ is _scannable_ can be determined by calling +isScannable()+. + +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. @@ -374,7 +457,7 @@ A +PropertyFilter+ is defined as follows: -------------------------------------------- // Functional Interface public interface PropertyFilter{ - String filterProperty(String value, FilterContext context); + PropertyValue filterProperty(PropertyValue value, FilterContext context); } -------------------------------------------- @@ -384,7 +467,7 @@ Hereby: * non null values are used as the current value of the key. Nevertheless for resolving multi-step dependencies filter evaluation has to be continued as long as filters are still changing some of the values to be returned. To prevent possible endless loops after a defined number of loops evaluation is stopped. -* +FilterContext+ provides additional metdata, including the key accessed, which is useful in many use cases. +* +FilterContext+ provides additional metdata, including the property accessed, which is useful in many use cases. This method is called each time a single entry is accessed, and for each property in a full properties result.