2) I think both approaches are feasible:
2a) A company (eg Credit Suisse) defines the complete config system and
provides with the infrastructure deployment. Users will never (and this is
good so, mess up with the platform config system).
2b) You want to setup all manually, so I think the builder support planned
by Oliver is the best. I originally also had some similar approach.
2c) The question is, if you prefer to register your built configurations
somehow, after having created it. Of if you want to have some factory
classes defined by the SPI, which you are then implementing... ?



2015-01-22 19:59 GMT+01:00 Romain Manni-Bucau <[email protected]>:

> 1) ok
>
> 2) we spoke about it earlier but I think here a builder would be the
> easiest and cleaner solution. Extensions can work on the builder IMO
> but shouldn't be able to modify at runtime the configuration itself.
>
>
> Romain Manni-Bucau
> @rmannibucau
> http://www.tomitribe.com
> http://rmannibucau.wordpress.com
> https://github.com/rmannibucau
>
>
> 2015-01-22 19:44 GMT+01:00 Anatole Tresch <[email protected]>:
> > Hi Romain¨
> >
> > so lets focus on the first aspect:
> >
> > 1) I would agree to provide ConfigurationProvider as an accessor
> singleton
> > class in Java 7 and 8 similarly. As a consequence I would agree to
> > remove Configuration.current()
> > in Java 8 and use ConfigurationProvider as the entry point into Tamaya
> > config.
> > 2) I would then define a ConfigurationProviderSpi, which implements
> exactly
> > how Configuration instances are managed, depending on the context or
> > whatever is appropriate. This class is loaded from the ServiceContext
> once
> > and then hold as a static variable within ConfigurationProvider. What is
> > happening inside ConfigurationProvider/ConfigurationProviderSpi is
> > basically completely transparent. In SE it will be true singleton, in
> > EE/OSGI environments something different perhaps.
> >
> > -> This should give you a direct OOTB API to decide how Configuration
> > instances are managed.
> >
> > 2a) If we would remove ConfigurationContext, we might add the method
> >
> > /**
> >      * This method can be used for programmatically adding {@link
> > PropertySource}s.
> >      * It is not needed for normal 'usage' by end users, but only for
> > Extension Developers!
> >      *
> >      * @param propertySourcesToAdd the PropertySources to add
> >      */
> >     void addPropertySources(PropertySource... propertySourcesToAdd);
> >
> > to the Configuration interface.
> >
> > 2b) The other methods look nevertheless somehow detailed, and when
> writing
> > extensions they may be still very helpful. So basically if we want to
> > remove ConfigurationContext completely some of them would end up on
> > Configuration.
> > Best we can do is probably to add a method ConfigurationContext
> > getContext() on Configuration, or on ConfigurationProvider. Disadvantage
> is
> > that PropertyFilter and PropertySource also get API artefacts (basically
> > PropertyConverter already is one, since it can be passed as parameter for
> > adhoc conversion), so let's see what Mark thinks on that...
> >
> > WDYT? Would that match at least first couple of aspects you mentioned?
> >
> > -Anatole
> >
> >
> > 2015-01-22 17:47 GMT+01:00 Romain Manni-Bucau <[email protected]>:
> >
> >> few more comments inline
> >>
> >>
> >>
> >> 2015-01-22 17:41 GMT+01:00 Tresch, Anatole <
> >> [email protected]>:
> >> > inline as usual
> >> >
> >> > 2015-01-22 16:56 GMT+01:00 Tresch, Anatole <
> >> [email protected]>:
> >> >> Feedback inline:
> >> >>
> >> >> -----Original Message-----
> >> >> From: Romain Manni-Bucau [mailto:[email protected]]
> >> >> Sent: Donnerstag, 22. Januar 2015 16:18
> >> >> To: [email protected]
> >> >> Subject: Re: PropertyQuery
> >> >>
> >> >> shouldnt prevent us to go futher but also means we make a lot of
> noise
> >> >> and no progress...
> >> >> -> That depends on the quality of discussion, not on the fact that we
> >> discuss ;). And if you say my posts are noise, well... I take that into
> >> account. Thanks.
> >> >>
> >> >
> >> > we all tend to do it but that's hard to follow where we are and
> >> > finally 1-2 people are doing the product which is bad IMO
> >> > -> I agree. And I also trying to motivate my colluegues to participate
> >> the discussions...
> >> >
> >> >> That said here the feedbacks I try to make precise:
> >> >> -> Nice, thanks!
> >> >>
> >> >> - java 7 module:
> >> >> -- ConfigurationProvider should be called ConfigurationFactory IMO
> (see
> >> next)
> >> >> -> NO! NO! NO! We already discussed multiple times that this is not
> >> necessarily a factory.
> >> >>
> >> >> - org.apache.tamaya.spi.ServiceContext#getServices should disappear
> ->
> >> >> no usage at least
> >> >> -> Of course it is used. How do you think the services in core are
> >> loaded from? Read the code before you state things that are not true or
> >> join our hangouts.
> >> >>
> >> >
> >> > not justified if you prefer. Said otherwise we shouldn't get a single
> >> > ServiceLoader abstraction since both needs are really different.
> >> > -> I do not agree here, but I am not sure I got your point.
> >> ServiceLoader is not powerful enough and users may want to use a
> different
> >> approach. Also for testing you might want to have a more flexible
> solution
> >> as well.
> >> >
> >>
> >> Point is we are exactly in between 2 states. We should either fuilly
> >> control programmatically the config config (the context more or less)
> >> with just good default fully overridable or not at all. ATM we can't
> >> fully control it but we can modify it a bit which is just a workaround
> >> IMO for several sub config cases.
> >>
> >> >
> >> >> -- Configuration.current() miss the "config" stage where you can
> >> >> select your impl: Configuration.byDefaultProvider() or
> >> >> Configuration.byProvider(MySuperProvider.class) and then we just call
> >> >> build() (or we can add in between addPropertySource/Converter). Doing
> >> >> it we don't need to cache
> >> >>
> >>
> org.apache.tamaya.spi.ServiceContextManager#serviceContextProviderDelegate
> >> >> which makes it more reliable
> >> >> -> Obviously you still in case of a factory, which it is not. It is a
> >> service!!!
> >> >
> >> > this is broken in most of environment...just test, check you leaked,
> >> > check you don't have the config you should etc...mainly works in SE
> >> > only where this abstraction is useless
> >> > -> Just a claim. Credit Suisse runs plusminus 800 plus instances also
> >> with low latency requirements successfully. Some are running in
> Weblogic,
> >> some in Tomcat, some standalone...
> >> >      Also here: your expertise is welcome, but your argument is simply
> >> not true.
> >> >
> >>
> >> Cause your property sources are not everywhere in the app parts I
> >> guess. You can say I can just switch the "locator" to solve it, it is
> >> true but not the default :(.
> >>
> >> >> -> For me it seems you are still stuck in the commons config design
> >> somehow. Oliver BTW is currently trying to build an extension module,
> where
> >> you can "build" your configuration in such/similar way.
> >> >>     So you can still do your own coding of everything there. We can
> >> then still discuss if we want to have that moved into the core/API part
> at
> >> a later stage.
> >> >>
> >> >> - org.apache.tamaya.spi.ConfigurationContext#context has no real
> >> >> meaning IMO and shouldn't be public if it is needed (it is not IMO)
> >> >> -> tbd. This could be an implementation detail, indeed (or I missed
> >> something).
> >> >>
> >> >> - org.apache.tamaya.spi.PropertySource#isScannable is not used ATM
> >> >> AFAIK so we should remove it IMO
> >> >> -> That is not true as well. Non scannable property source are not
> >> called for Configuration.getProperties().
> >> >>
> >> >
> >> > ok - I should have a cache issue in Idea, sorry
> >> > ->  fair enough.
> >> >
> >> >
> >> >> - I'd remove org.apache.tamaya.ConfigOperator and just allow to
> export
> >> >> a Config as a Map -> then use Map API to actually "map"
> >> >> - ConfigQuery -> same as previous comment
> >> >> -> adapt Configuration with 2 previous comments
> >> >> -> Well, JSR 310 as well as JSR 354 use this concept very
> successfully.
> >> I would definitively deny removing it. If you don’t get it talk with
> >> Stephen Colebourne.
> >> >> -> In many cases exporting to the full Map is not necessary.
> >> >> -> Creating of views will get implementation dependent.
> >> >> -> Summarizing: no way! IMO useless and inefficient proposal compared
> >> to what we have.
> >> >>
> >> >> - finally check it does worth to keep this j8 module (think only
> >> >> drawback removing it would be to loose Configuration.current() - or
> >> >> new equivalent - which is not a big deal IMO.
> >> >>
> >> >> -> Again this is not true again. There are as well the additional
> >> accessor using Optional, which are legit additions if someone uses Java
> 8.
> >> >
> >> > yep which is a very poor gain IMO for a lot of complexity:
> >> > -> on our side
> >> > -> on user side (in real life you often have multiple java version so
> >> > multiple apis?)
> >> > -> fair enough. your opinion, I have another one!
> >> >
> >> >> -> And to say it again once more: if you don’t want to support Java 8
> >> as a first citizen, many people here on the list would probably leave
> the
> >> project.
> >> >>
> >> > please shout guys if that statement is true
> >> >
> >> > -> yes please!
> >> >
> >> >>
> >> >>
> >> >> Romain Manni-Bucau
> >> >> @rmannibucau
> >> >> http://www.tomitribe.com
> >> >> http://rmannibucau.wordpress.com
> >> >> https://github.com/rmannibucau
> >> >>
> >> >>
> >> >> 2015-01-22 16:01 GMT+01:00 Tresch, Anatole <
> >> [email protected]>:
> >> >>> Hi Romain
> >> >>>
> >> >>>>well why I want to step back is just cause we slowly leave config
> >> >>>>field and we are implementing a storage solution.
> >> >>>
> >> >>> Do we? I am only focused on config related use cases and know about
> >> what I am talking:
> >> >>> - Exposing a part of the internals as API does not make a storage
> >> solution.
> >> >>> - Using TypeLiteral for property conversion does not have anything
> in
> >> common with a storage solution.
> >> >>>
> >> >>>  -> So please stay on the topic and keep off things that are not
> >> relevant, please.
> >> >>>
> >> >>>>There are already
> >> >>>>numerous projects doing it at apache - even if they can sometimes
> >> >>>>mandate some infra - so we should stick to the first goal of tamaya.
> >> >>>
> >> >>> -> Which is providing a configuration solution. I have well defined
> >> and well important use cases. If you don’t have them, well...
> >> >>> -> I do not care (too much) what other projects do. Often others
> >> provide good features, but also some less good ones. To argue not to
> >> repeat, what others did
> >> >>>     IMO is useless. We should take the good things and combine it
> >> here, so we get a good solution. And again: if you have something that
> >> disturbs you, be
> >> >>>     explicit. Just claiming or writing down your feelings does not
> >> help anybody here. Either you write down your concerns clearly, at the
> end
> >> by code, or your input
> >> >>>    is not much of use. It is that simple IMO. I am exposing me by
> >> writing down and trying to do things as Java API, simply because that is
> >> the only way it works to get
> >> >>>    a common understanding. Sorry for the hard words here.
> >> >>>
> >> >>>> I also not fully agree with the basis - in particular the SPI to be
> >> >>>> clear - we have ATM.
> >> >>>>
> >> >>>>To sumamrize a first release with:
> >> >>>>1) SPI ("provider" + property source)
> >> >>>>2) basic merge/conflict policy
> >> >>>>3) String read API
> >> >>>>4) basic convertion support
> >> >>>>
> >> >>>>Is far enough IMO.
> >> >>>>
> >> >>>>Once all of it is clear I'd like we do a release to gather feedback
> >> >>>>then continue building on top of it - we are ATM in the tunnel ;).
> >> >>>
> >> >>> -> So we have a scope discussion for the new release now. IMO the
> >> current artifacts within the API are clearly in focus for release 1
> (from
> >> an API perspective). If you want to remove anything, you should
> >> >>>      exactly write down, WHAT should be removed and also WHY.
> >> >>> -> About Collection support, we may have a vote on it. Or other
> people
> >> here on the mailing list should add their cents ;)
> >> >>> -> Gathering feedback is OK. Nevertheless we can mark the release as
> >> alpha, so everybody is clear that things may still change.
> >> >>> -> And again discussing what should be part of release 1 IMO must
> not
> >> constrain us to discuss on further concepts as long as the threads are
> >> clearly separated and not too many. So help us constructively with the
> >> >>>     discussion instead of throwing woods into our legs all the
> times.
> >> That would be great!
> >> >>>
> >> >>>
> >> >>> Romain Manni-Bucau
> >> >>> @rmannibucau
> >> >>> http://www.tomitribe.com
> >> >>> http://rmannibucau.wordpress.com
> >> >>> https://github.com/rmannibucau
> >> >>>
> >> >>>
> >> >>> 2015-01-22 13:47 GMT+01:00 Tresch, Anatole <
> >> [email protected]>:
> >> >>>> Hi Romain/all
> >> >>>>
> >> >>>> I think we have quite a common agreement on the basic functions
> >> designed so far and I do not want to
> >> >>>> reinvent or change any of the basic mechanism. I simply come up
> with
> >> a simple request to use the algorithm pattern
> >> >>>> for a small subset of a functionality (how the final property value
> >> is evaluated). The usage of TypeLiteral was even your
> >> >>>> own proposal AFAIK, when we discussed PropertyConverters ;) ).
> >> >>>>
> >> >>>> Our current configuration model in general IMO is a very good
> start.
> >> It is already so flexible that I can implement 60-70% of use cases
> >> >>>> I have currently in use within Credit Suisse (this is somehow my
> >> "benchmark", which from my discussions I had during the last years
> covers a
> >> >>>> majority of use cases when dealing with distributed and modular
> >> systems).
> >> >>>>
> >> >>>> I am sure you remember, we had a discussion on another mail thread
> >> yesterday about Collection support. My proposal
> >> >>>> basically is the outcome of having played around to extend our API
> to
> >> support collections based only on Map<String,String>
> >> >>>> only as internal PropertySource representation thus avoiding the
> >> String[] getListProperty(String) methods.
> >> >>>>
> >> >>>> So for getting type information and define the content type of
> >> collections we need TypeLiterals, which similarly is useful perhaps for
> >> other non collection
> >> >>>> cases.  Since collection entries can be defined in different
> property
> >> sources, a final list may want to contain all the properties found,
> instead
> >> of overriding,
> >> >>>> so values of different property sources are to be  combined. AFAIK
> >> you already agreed on that UC. Hardcoding yet another strategy IMO makes
> >> >>>> no sense, so I would recommend use the default for all common
> aspects
> >> (that is what we already have in place) and add support for adapting the
> >> default
> >> >>>> where it is not appropriate. Thinking on this IMO both aspects
> >> (TypeLiterals and the collector) are the same for evaluating single
> >> property values as well,
> >> >>>> so regarding that it makes no sense to model collections
> differently,
> >> but extend/flexibilize the way how we can access properties in general.
> >> >>>>
> >> >>>> I tried to combine both aspects in one class, which I called
> >> PropertyQuery. Perhaps also the name PropertyQuery is confusing.
> Alternates
> >> would be
> >> >>>> PropertyRequest, PropertyAccess,... or whatever you like, I am
> >> completely open here ;)
> >> >>>>
> >> >>>> We can postpone that discussion, but just stopping this discussion
> >> now will not solve anything. Also we already invested a lot of
> discussing
> >> collection support, why stop here.
> >> >>>> We have enough time I think. We have important use cases to solve
> >> that may affect the Configuration interface as a whole. Adding them
> later
> >> may be a bad idea, so we
> >> >>>> should sort out these things now IMO.
> >> >>>>
> >> >>>> So I am curious to see your concrete (improvement) proposals ;), so
> >> we can continue to see, if we end up in a common view. If so, others on
> the
> >> mailing list also have a
> >> >>>> chance to join us again, I think.
> >> >>>>
> >> >>>> Anatole
> >> >>>>
> >> >>>>
> >> >>>> -----Original Message-----
> >> >>>> From: Romain Manni-Bucau [mailto:[email protected]]
> >> >>>> Sent: Donnerstag, 22. Januar 2015 09:45
> >> >>>> To: [email protected]
> >> >>>> Subject: Re: PropertyQuery
> >> >>>>
> >> >>>> not exactly, it is different to expose MapReduce in API and to
> >> >>>> implement it behind another concept, ATM it is an implementation
> >> >>>> detail.
> >> >>>>
> >> >>>> Why I worry a bit about Query stuff is we start to leave
> configuration
> >> >>>> layer to enter backend one, not sure it does worth it *to start* -
> I
> >> >>>> understand your feature even if I never needed it but I'd really
> like
> >> >>>> we ensure our basis are solid enough before adding features on top
> of
> >> >>>> them.
> >> >>>>
> >> >>>> Said otherwise I think we should now focus on trying to make a 0.1
> -
> >> >>>> we can add alpha to make obvious we are not done - and stop adding
> >> >>>> anything before being fully agree on all we have.
> >> >>>>
> >> >>>> Does it make sense?
> >> >>>>
> >> >>>>
> >> >>>>
> >> >>>> Romain Manni-Bucau
> >> >>>> @rmannibucau
> >> >>>> http://www.tomitribe.com
> >> >>>> http://rmannibucau.wordpress.com
> >> >>>> https://github.com/rmannibucau
> >> >>>>
> >> >>>>
> >> >>>> 2015-01-22 9:39 GMT+01:00 Anatole Tresch <[email protected]>:
> >> >>>>> Hi Romain
> >> >>>>>
> >> >>>>> About lamba friendly I can still have a Builder that creates a
> >> query. Works perfectly.
> >> >>>>> The default use cases would remain as is. Queries would just add
> >> about 3 methods to Configuration. We get as well all the flexibility we
> >> would need for collection support as well ;)
> >> >>>>>
> >> >>>>> Mapreduce? Well what else is evaluating a chain of propsources by
> >> overridding? Its already there, but hardcoded the same, which is
> obviously
> >> not flexible enough!
> >> >>>>>
> >> >>>>> -
> >> >>>>> Anatole Tresch
> >> >>>>> Glärnischweg 10
> >> >>>>> 8620 Wetzikon
> >> >>>>> Tel +41 (43) 317 05 30
> >> >>>>> -
> >> >>>>> Send from Mobile
> >> >>>>>
> >> >>>>>> Am 22.01.2015 um 09:11 schrieb Romain Manni-Bucau <
> >> [email protected]>:
> >> >>>>>>
> >> >>>>>> isnt it too complicated for most common use cases (+ not that
> lambda
> >> >>>>>> friendly cause of the 4 parameters which dont help writing
> readable
> >> >>>>>> code IMO).
> >> >>>>>>
> >> >>>>>> Functionally it works but it makes default cases "hard" and
> actually
> >> >>>>>> you just want to implement the MapReduce pattern so maybe we
> should
> >> >>>>>> call it this way if we go this way.
> >> >>>>>>
> >> >>>>>>
> >> >>>>>> Romain Manni-Bucau
> >> >>>>>> @rmannibucau
> >> >>>>>> http://www.tomitribe.com
> >> >>>>>> http://rmannibucau.wordpress.com
> >> >>>>>> https://github.com/rmannibucau
> >> >>>>>>
> >> >>>>>>
> >> >>>>>> 2015-01-22 8:44 GMT+01:00 Anatole Tresch <[email protected]>:
> >> >>>>>>> Dear all
> >> >>>>>>>
> >> >>>>>>> *let's think about additional use cases:*
> >> >>>>>>> 1) as mentioned in my last mail about collection types,*
> >> overriding may not
> >> >>>>>>> always be the right resolution policy *for accessing a
> configured
> >> value
> >> >>>>>>> (e.g. for collecting all configured values in a final set/list).
> >> >>>>>>> 2) sometimes I want to define my own PropertyConverters (already
> >> >>>>>>> implemented)
> >> >>>>>>> 3) sometimes I even would like to evaluate multiple keys taking
> >> the result
> >> >>>>>>> of the first property key that returns a config property (nice
> >> convenience)
> >> >>>>>>>
> >> >>>>>>> When we will add all this kind of aspect into Configuration, we
> >> will end up
> >> >>>>>>> in a messy interface, e.g. for
> >> >>>>>>> String get(String);
> >> >>>>>>> <T> T get(String, Class<T>);
> >> >>>>>>> <T> T get(String, Class<T>, PropertyConverter);
> >> >>>>>>>
> >> >>>>>>> String get(String, ValueCollector);
> >> >>>>>>> <T> T get(String, Class<T>, ValueCollector);
> >> >>>>>>> <T> T get(String, Class<T>, PropertyConverter, ValueCollector);
> >> >>>>>>> ...
> >> >>>>>>>
> >> >>>>>>> Obviously that does not make sense.
> >> >>>>>>>
> >> >>>>>>> Instead of I would propose, we would define a PropertyQuery,
> which
> >> >>>>>>> basically is
> >> >>>>>>>
> >> >>>>>>>   - is the same as a TypeLiteral<T> solving the type aspects
> >> >>>>>>>   - has a list of *keys* to be evaluated, at least one
> >> >>>>>>>   - optionally has a ValueCollector
> >> >>>>>>>   - optionally has a list of PropertyConverter
> >> >>>>>>>
> >> >>>>>>> With that our interface gets much leaner, but still flexible
> >> enough to
> >> >>>>>>> accommodate the use cases above:
> >> >>>>>>>
> >> >>>>>>> String get(String);
> >> >>>>>>> <T> T get(String, Class<T>);
> >> >>>>>>> <T> T get(String, Class<T>, PropertyConverter); // may be
> ommitted
> >> as well ?
> >> >>>>>>> <T> get(PropertyQuery<T> query);
> >> >>>>>>> ...
> >> >>>>>>>
> >> >>>>>>> This solves all use cases above and gives us an easy way to add
> >> additional
> >> >>>>>>> feature, if needed (I dont see any, but who knows). Hereby
> >> ValueCollector
> >> >>>>>>> would be defined as follows:
> >> >>>>>>>
> >> >>>>>>> @FunctionalInterface
> >> >>>>>>> public interface ValueCollector {
> >> >>>>>>>
> >> >>>>>>>    /**
> >> >>>>>>>     * Method that is called for each value returned by a
> >> PropertySource
> >> >>>>>>> for the given key.
> >> >>>>>>>     * @param currentValue the current value, including 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
> >> >>>>>>>     *                     result to be used as new {@code
> >> currentValue}.
> >> >>>>>>>     * @param key The current key to be evaluated.
> >> >>>>>>>     * @param newValue the new value read from the current {@code
> >> >>>>>>> propertySource}, not null.
> >> >>>>>>>     * @param propertySource The PropertySource that returned the
> >> current
> >> >>>>>>> value (either as the result of a direct
> >> >>>>>>>     *                       access of as a property Map
> containing
> >> the
> >> >>>>>>> given key. The PropertySource given
> >> >>>>>>>     *                       may be evaluated for additional
> >> meta-data, how
> >> >>>>>>> the given values are to be combined.
> >> >>>>>>>     * @return the value to be used for future evaluation.
> >> >>>>>>>     */
> >> >>>>>>>    String collect(String key, String newValue, PropertySource
> >> >>>>>>> propertySource,
> >> >>>>>>>                   String currentValue);
> >> >>>>>>>
> >> >>>>>>>    /**
> >> >>>>>>>     * Default overriding collector.
> >> >>>>>>>     */
> >> >>>>>>>    public final ValueCollector DEFAULT_OVERRIDING_COLLECTOR =
> (k,
> >> nv, ps,
> >> >>>>>>> cv) -> nv;
> >> >>>>>>> }
> >> >>>>>>>
> >> >>>>>>> Feedback?
> >> >>>>>>>
> >> >>>>>>> Cheers,
> >> >>>>>>> Anatole
> >>
> >
> >
> >
> > --
> > *Anatole Tresch*
> > Java Engineer & Architect, JSR Spec Lead
> > Glärnischweg 10
> > CH - 8620 Wetzikon
> >
> > *Switzerland, Europe Zurich, GMT+1*
> > *Twitter:  @atsticks*
> > *Blogs: **http://javaremarkables.blogspot.ch/
> > <http://javaremarkables.blogspot.ch/>*
> >
> > *Google: atsticksMobile  +41-76 344 62 79*
>



-- 
*Anatole Tresch*
Java Engineer & Architect, JSR Spec Lead
Glärnischweg 10
CH - 8620 Wetzikon

*Switzerland, Europe Zurich, GMT+1*
*Twitter:  @atsticks*
*Blogs: **http://javaremarkables.blogspot.ch/
<http://javaremarkables.blogspot.ch/>*

*Google: atsticksMobile  +41-76 344 62 79*

Reply via email to