Tbd. As of now my idea was to use Java to define the meta level. Or whatever language is running on the jvm with tamaya... But the corresponding concepts/ideas are not yet/only partially there as of now... Werner Keil <werner.k...@gmail.com> schrieb am Do., 4. Dez. 2014 um 15:20:
> While using XML a lot of it can be found that Multiconf did in Python. > > (I am pretty sure most of Spring Config still uses plenty of XML, too, in > theory similar to Multiconf it could use a Groovy DSL, maybe if Pivotal > used Tamaya some day and the Groovy experts here considered such DSL a > worthy effort?;-D) > > > > > On Thu, Dec 4, 2014 at 2:53 PM, Tresch, Anatole < > anatole.tre...@credit-suisse.com> wrote: > > > Hi Mark > > > > let me do a last try to clarifiy my ideas, I am open to discuss things > > (and do add some ideas at the end, so we can start the discussions right > > away ;) ): > > > > 1) my idea was to define a minimalistic interface for properties first. > It > > should as simple as possible to implement. Just using Map<String,String> > I > > found not optimal, since a Map requires several methods that are not easy > > to implement in all cases, such as size(). Also Spring provides such a > > similarl abstraction(PropertySource). For this I created > PropertyProvider. > > 2) Looking at Configuration there is much more functionality needed to > > have a powerful config API, such as type support (getInt, getBoolean, > > getAdapted), registering of listeners, extension points (with, query). > From > > our bank > > additional methods were added for evaluation of the key ranges > present, > > assuming hereby a.b.d: a is an area, containing an area b containing a > key > > d. So I defined the Configuration interface. > > 3) Now there are very common types of properties sources you want to read > > from. I personally identified: classpath resources, files and URLs/URIs. > So > > I added some kind of factory class (PropertyProviders), which allows to > > easily > > construct them descriptively: PropertyProvider proc = > > PropertyProviders.fromPath("classpath:META-INF/cfg/config.ini"); > > 4) In many companies you do not have a fixed configuration file name, you > > will have locations, where you consume all files (even recursively). So > > adding resource loader support similar to Spring was compelling: > > PropertyProvider proc = > > PropertyProviders.fromPath("classpath:META-INF/cfg/**/*.ini"); > > 5) Looking at what we have in Credit Suisse and what other prople told > > they have in their companies, simple priority based adding of maps is not > > enough. There are cases, where I want to filter out values, prevent > > overriding of certain values etc. Also different locations (classpath, > > files, remote) are mixed and depending on the source different priorities > > may be assigned. Finally configuration pairs themselves can be attributed > > (default entries, global default entries, explicit entries, ..), which > also > > lead to different configuration priorities within the same source: or > even > > config file, e.g: > > > > <config> > > <defaults> > > <a>aValue</a> > > <b>bValue</b> > > </deault> > > > > <pluginConfig plugin="abc"> > > <a>aValue2</a> > > </pluginConfig> > > > > <server ip="1.2.4.5"> > > <b>bValue2</b> > > </server> > > </config> > > > > Since I saw definitively the most complex scenarios I wanted to support > > power users doing that kind of modelling more easily. One mechanism to > > achive this is allowing to aggregate and combine maps (=providers), so > > I added the combination methods on PropertyProviders like aggregate, > > intersect, filter, ... > > Now this seems more complicated for you guys than it seems for me ;) I > can > > imagine different things that may be simplified: > > > > - Remove PropertyProvider/ PropertyProviders from the API part and just > > add corresponding functionality using a ConfigurationBuilder: > > > > Configuration config = > > ConfigurationBuilder.create("myConfig").addPaths("ab/B/B", > > "../fhgg.xml").with(AggregationPolicy.OVERRIDE). > addPaths("jhbjh/kjhkjh/").build(); > > Config aggregatedConfig = config.with(Aggregators.from(config); > > > > - We still could put the PropertyProvider to the core implementation > > module, or even add it as a separate module, for the ones that like a > more > > leightweight implementation SPI ;) > > > > Configuration conf = Configuration.current(); will still be the accessor > > method of choice. Though I am well aware of the fact that the > abstractions > > (SPIs) required to evaluate the right configuration during runtime is > not > > yet discussed. Also the current state in the repo in that area is far > away > > from finished (I currently try to cleanup a few things, especially > > artifacts that are duplicates...). > > > > Best, > > Anatole > > > > > > > > -----Original Message----- > > From: Mark Struberg [mailto:strub...@yahoo.de] > > Sent: Donnerstag, 4. Dezember 2014 11:08 > > To: dev@tamaya.incubator.apache.org > > Subject: Re: UC: Combining PropertyProvider Instances > > > > I think I need a bit time to understand this. I've tried to grasp it for > 2 > > days now and this might mean that it is too complicated if not even I get > > it. Why are we doing this so complicated? Pulling in all the database > logic > > into a tool which main target is that it should be really easy to use? > > What benefit does this add over hiding those details? e.g. in DeltaSpike > I > > would just add a DatabaseConfigSource and be done. The user would not > even > > see that it magically picks up the values from the db then. > > > > > > LieGrue, > > strub > > > > > > > > > > > > > On Tuesday, 2 December 2014, 14:02, Anatole Tresch <anat...@apache.org > > > > wrote: > > > > Hi all > > > find following an additional part of use cases for comment. Note that > > this > > > area IMO definitively may be improved in several ways. Always keep in > > mind > > > that I try to setup the design guide similarly in parallel. It can be > > > easily accessed from the GH mirror: > > > > > > > > https://github.com/apache/incubator-tamaya/blob/master/ > docs/design/2_CoreConcepts.adoc > > > > > > Cheers, > > > Anatole > > > > > > Combining Property Providers > > > > > > Looking at the structures of configuration system used by large > companies > > > we typically encounter some kind of configuration hierarchies that are > > > combined in arbitrary ways. Users of the systems are typically not > aware > > of > > > the complexities in this area, since they simply know the possible > > > locations, formats and the overriding policies. Framework providers on > > the > > > other side must face the complexities and it would be very useful if > > Tamaya > > > can support here by providing prebuilt functionality that helps > > > implementing these aspects. All this leads to the feature set of > > combining > > > property providers. Hereby the following strategies are useful: > > > > > > - > > > > > > aggregating providers, hereby later providers added > > > - > > > > > > override any existing entries from earlier providers > > > - > > > > > > combine conflicting entries from earlier providers, e.g. into a > > > comma-separated structure. > > > - > > > > > > may throw a ConfigExcepotion ig entries are conflicting > > > - > > > > > > may only add entries not yet defined by former providers, > > preventing > > > entries that are already present to be overwritte > > > - > > > > > > any custom aggregation strategy, which may be a mix of above > > > - > > > > > > intersecting providers > > > - > > > > > > subtracting providers > > > - > > > > > > filtering providers > > > > > > These common functionality is provided by the PropertyProviders > > > singleton. Additionally to the base strategies above a MetaInfo > instance > > > can be passed optionally as well to define the meta information for the > > > newly created provider instances. Let’s assume we have two property > > > providers with the following data: > > > Provider 1 > > > > > > a=a > > > b=b > > > c=c > > > g=g > > > h=h > > > i=i > > > > > > Provider 2 > > > > > > a=A > > > b=B > > > c=C > > > d=D > > > e=E > > > f=F > > > > > > Looking in detail you see that the entries a,b,c are present in both > > > providers, whereas d,e,f are only present in provider 1, and g,h,i only > > in > > > provider 2. > > > Example Combining PropertyProviders > > > > > > PropertyProvider provider1 = ... > > > PropertyProvider provider2 = ... > > > // aggregate, hereby values from provider 2 override values from > > provider 1 > > > PropertyProvider unionOverriding = > > > PropertyProviders.aggregate(AggregationPolicy.OVERRIDE(), provider1, > > > provider2);*System*.out.println("unionOverriding: " + > > > unionOverriding); > > > // ignore duplicates, values present in provider 1 are not overriden > > > by provider 2 > > > PropertyProvider unionIgnoringDuplicates = > > > PropertyProviders.aggregate(AggregationPolicy.IGNORE_DUPLICATES(), > > > provider1, provider2);*System*.out.println("unionIgnoringDuplicates: " > > > + unionIgnoringDuplicates); > > > // this variant combines/maps duplicate values into a new value > > > PropertyProvider unionCombined = > > > PropertyProviders.aggregate(AggregationPolicy.COMBINE(), provider1, > > > provider2);*System*.out.println("unionCombined: " + unionCombined); > > > // This variant throws an exception since there are key/value paris in > > > both providers, but with different values*try*{ > > > PropertyProviders.aggregate(AggregationPolicy.EXCEPTION(), > > > provider1, provider2); > > > }*catch*(ConfigException e){ > > > // expected! > > > } > > > > > > The example above produces the following outpout: > > > Example Combining PropertyProviders > > > > > > AggregatedPropertyProvider{ > > > (name = dynamicAggregationTests) > > > a = "[a][A]" > > > b = "[b][B]" > > > c = "[c][C]" > > > d = "[D]" > > > e = "[E]" > > > f = "[F]" > > > g = "[g]" > > > h = "[h]" > > > i = "[i]" > > > } > > > unionOverriding: AggregatedPropertyProvider{ > > > (name = <noname>) > > > a = "A" > > > b = "B" > > > c = "C" > > > d = "D" > > > e = "E" > > > f = "F" > > > g = "g" > > > h = "h" > > > i = "i" > > > } > > > unionIgnoringDuplicates: AggregatedPropertyProvider{ > > > (name = <noname>) > > > a = "a" > > > b = "b" > > > c = "c" > > > d = "D" > > > e = "E" > > > f = "F" > > > g = "g" > > > h = "h" > > > i = "i" > > > } > > > unionCombined: AggregatedPropertyProvider{ > > > (name = <noname>) > > > a = "a,A" > > > b = "b,B" > > > c = "c,C" > > > d = "D" > > > e = "E" > > > f = "F" > > > g = "g" > > > h = "h" > > > i = "i" > > > } > > > > > > No AggregationPolicy is also an interface that can be implemented: > > > AggregationPolicy Interface > > > > > > @FunctionalInterface*public* *interface* *AggregationPolicy* { > > > *String* aggregate(*String* key, *String* value1, *String* value2); > > > } > > > > > > So we can also define our own aggregation strategy using a Lambda > > > expression: > > > Use a Custom AggregationPolicy > > > > > > PropertyProvider provider1 = ...; > > > PropertyProvider provider2 = ...; > > > PropertyProvider props = PropertyProviders.aggregate( > > > (k, v1, v2) -> (v1 != null ? v1 : "") + '[' + v2 + > > > "]", > > > MetaInfo.of("dynamicAggregationTests"), > > > props1, props2);*System*.out.println(props); > > > > > > Additionally we also pass here an instance of MetaInfo. The output of > > > this code snippet is as follows: > > > Listing of dynamic aggregation policy > > > > > > AggregatedPropertyProvider{ > > > (name = dynamicAggregationTests) > > > a = "[a][A]" > > > b = "[b][B]" > > > c = "[c][C]" > > > d = "[D]" > > > e = "[E]" > > > f = "[F]" > > > g = "[g]" > > > h = "[h]" > > > i = "[i]" > > > } > > > > > > Summarizing the PropertyProviders singleton allows to combine > providers > > > in various forms: > > > Methods provided on PropertyProviders > > > > > > public final class PropertyProviders { > > > > > > private PropertyProviders() {} > > > > > > public static PropertyProvider fromArgs(String... args) { > > > public static PropertyProvider fromArgs(MetaInfo metaInfo, > String... > > args) > > > { > > > public static PropertyProvider fromPaths(AggregationPolicy > > > aggregationPolicy, String... paths) { > > > public static PropertyProvider fromPaths(String... paths) { > > > public static PropertyProvider fromPaths(List<String> paths) { > > > public static PropertyProvider fromPaths(AggregationPolicy > > > aggregationPolicy, List<String> paths) { > > > public static PropertyProvider fromPaths(MetaInfo metaInfo, > > > List<String> paths) { > > > public static PropertyProvider fromPaths(AggregationPolicy > > > aggregationPolicy, MetaInfo metaInfo, List<String> paths) { > > > public static PropertyProvider fromUris(URI... uris) { > > > public static PropertyProvider fromUris(AggregationPolicy > > > aggregationPolicy, URI... uris) { > > > public static PropertyProvider fromUris(List<URI> uris) { > > > public static PropertyProvider fromUris(AggregationPolicy > > > aggregationPolicy, List<URI> uris) { > > > public static PropertyProvider fromUris(MetaInfo metaInfo, URI... > > uris) > > > { > > > public static PropertyProvider fromUris(AggregationPolicy > > > aggregationPolicy, MetaInfo metaInfo, URI... uris) { > > > public static PropertyProvider fromUris(MetaInfo metaInfo, > List<URI> > > > uris) { > > > public static PropertyProvider fromUris(AggregationPolicy > > > aggregationPolicy, MetaInfo metaInfo, List<URI> uris) { > > > public static PropertyProvider fromMap(Map<String, String> map) { > > > public static PropertyProvider fromMap(MetaInfo metaInfo, > > > Map<String, String> map) { > > > public static PropertyProvider empty() { > > > public static PropertyProvider emptyMutable() { > > > public static PropertyProvider empty(MetaInfo metaInfo) { > > > public static PropertyProvider emptyMutable(MetaInfo metaInfo) { > > > public static PropertyProvider fromEnvironmentProperties() { > > > public static PropertyProvider fromSystemProperties() { > > > public static PropertyProvider freezed(PropertyProvider provider) { > > > public static PropertyProvider aggregate(AggregationPolicy > > > mapping, MetaInfo metaInfo, PropertyProvider... providers){ > > > public static PropertyProvider aggregate(PropertyProvider... > > providers) > > > { > > > public static PropertyProvider aggregate(List<PropertyProvider> > > > providers) { > > > public static PropertyProvider aggregate(AggregationPolicy > > > mapping, PropertyProvider... propertyMaps) { > > > public static PropertyProvider aggregate(AggregationPolicy > > > mapping, List<PropertyProvider> providers) { > > > public static PropertyProvider mutable(PropertyProvider provider) { > > > public static PropertyProvider intersected(AggregationPolicy > > > aggregationPolicy, PropertyProvider... providers) { > > > public static PropertyProvider intersected(PropertyProvider... > > providers) > > > { > > > public static PropertyProvider subtracted(PropertyProvider target, > > > PropertyProvider... providers) { > > > public static PropertyProvider filtered(Predicate<String> filter, > > > PropertyProvider provider) { > > > public static PropertyProvider > > > contextual(Supplier<PropertyProvider> mapSupplier, > > > Supplier<String> > > > isolationKeySupplier) { > > > public static PropertyProvider delegating(PropertyProvider > > > mainMap, Map<String, String> parentMap) { > > > public static PropertyProvider replacing(PropertyProvider mainMap, > > > Map<String, String> replacementMap) { > > > } > > > > > >