So I pushed my latest changes, which include the work discussed here.
I really like it better, for both having a single method for both
consumers/producers (while still having separate interfaces when the
options are specific to the consumer/producer), and having a separate set
of interfaces for advanced options, so that the choice when completing is
minimized.
Let me know what you think...
The file endpoint builder DSL is available at
https://github.com/apache/camel/blob/endpoint-dsl/core/camel-core/src/main/java/org/apache/camel/model/endpoint/FileEndpointBuilderFactory.java

Le mer. 12 juin 2019 à 19:17, Guillaume Nodet <gno...@apache.org> a écrit :

> A compiling prototype is available at
> https://gist.github.com/gnodet/ad5e00ec8e6855bbdab3d6f58d8ced80
>
> However, this can't be combined with Claus' suggestion to keep some kind
> of hierarchy between the builders.
>
> Though we could make the properties flagged with the "advanced" label
> accessible using the advanced() / basic() methods in the below example.
>   https://gist.github.com/gnodet/aa393baada9c0819cfcba01d7261b943
>
> So at the end, the choice is between
>
>    - two methods fromFile() / toFile() and the ability to make options in
>    a hierarchy
>    - a single method file() for both consumers / producers with the
>    ability to group advanced options in a separate interface to split them a
>    bit from the basic options
>
> I would tend to favour the second option, as I think the benefit of moving
> the advanced properties apart is greater than the ability to have them in a
> hierarchy.
>
> Cheers,
> Guillaume
>
> Le mer. 12 juin 2019 à 17:15, Guillaume Nodet <gno...@apache.org> a
> écrit :
>
>> I'll experiment a bit, but your suggestion looks promising.
>>
>> Le mer. 12 juin 2019 à 15:24, Jan Bednář <pub...@janbednar.eu> a écrit :
>>
>>> Hi all, one idea, how to keep clean file() instead fromFile() and
>>> toFile(). I have not checked full code of source branch, so apologize,
>>> if this is not possible to integrate for some reason.
>>>
>>> I think it is not needed to know if you are consumer or producer when
>>> creating builder. It can be switched to consumer/producer builder
>>> afterwards, when consumer/producer specific builder method is used.
>>>
>>> There could be two interfaces FileEndpointConsumerBuilder and
>>> FileEndpointProducerBuilder. Consumer builder interface holds common and
>>> consumer-only options. Producer builder interface holds common and
>>> producer-only options. Builder class implements
>>> FileEndpointConsumerBuilder and FileEndpointProducerBuilder. Common
>>> methods returns builder self. Producer-only methods returns builder
>>> casted to FileEndpointProducerBuilder. Consumer-only methods returns
>>> builder casted to FileEndpointConsumerBuilder;
>>>
>>> With this, first call to builder method, which is consumer-only returns
>>> FileEndpointConsumerBuilder and user is forced to use only common and
>>> consumer-only options for the subsequent calls.
>>>
>>> This is a bit strange, to have two different contracts for the same
>>> method in interfaces, but compiller does not complain about it.
>>>
>>> Small silly draft:
>>>
>>> public interface FileEndpointProducerBuilder extends EndpointBuilder {
>>>          FileEndpointProducerBuilder fileExist(GenericFileExist
>>> fileExist); // producer only
>>>          FileEndpointProducerBuilder autoCreate(boolean autoCreate); //
>>> common
>>>          FileEndpointProducerBuilder flatten(boolean flatten); //common
>>> }
>>>
>>> public interface FileEndpointConsumerBuilder extends EndpointBuilder {
>>>          FileEndpointConsumerBuilder recursive(boolean recursive); //
>>> consumer only
>>>          FileEndpointConsumerBuilder autoCreate(boolean autoCreate);
>>> //common
>>>          FileEndpointConsumerBuilder flatten(boolean flatten); //common
>>> }
>>>
>>> public class FileEndpointBuilderImpl implements
>>> FileEndpointProducerBuilder, FileEndpointConsumerBuilder {
>>>          private FileEndpoint endpoint;
>>>
>>>          public FileEndpointBuilderImpl(String path) {
>>>                  this.endpoint = new FileEndpoint();
>>>                  this.endpoint.setFile(new File(path)); // required
>>>          }
>>>
>>>          public FileEndpointConsumerBuilder recursive(boolean recursive)
>>> { // consumer only, return FileEndpointConsumerBuilder
>>>                  this.endpoint.setRecursive(recursive);
>>>                  return this;
>>>          }
>>>
>>>          public FileEndpointProducerBuilder fileExist(GenericFileExist
>>> fileExist) { // producer only, return FileEndpointProducerBuilder
>>>                  this.endpoint.setFileExist(fileExist);
>>>                  return this;
>>>          }
>>>
>>>          public FileEndpointBuilderImpl autoCreate(boolean autoCreate) {
>>> // common, return FileEndpointBuilderImpl which allows user to use all
>>> options
>>>                  this.endpoint.setAutoCreate(autoCreate);
>>>                  return this;
>>>          }
>>>
>>>          public FileEndpointBuilderImpl flatten(boolean autoCreate) { //
>>> common, return FileEndpointBuilderImpl which allows user to use all
>>> options
>>>                  this.endpoint.setFlatten(autoCreate);
>>>                  return this;
>>>          }
>>>
>>>          @Override
>>>          public Endpoint build() {
>>>                  return endpoint;
>>>          }
>>> }
>>>
>>>
>>> Dne 11.6.2019 v 23:36 Guillaume Nodet napsal(a):
>>> > Le mar. 11 juin 2019 à 20:45, Alex Dettinger <aldettin...@gmail.com> a
>>> > écrit :
>>> >
>>> >> Hey Guillaume, nice feature indeed.
>>> >> Just a detail when reading the example, I think one could be
>>> surprised to
>>> >> have x2 from/to at first glance, I mean:
>>> >> from(fromFile(... and to(toFile(...
>>> >>
>>> >>
>>> > I do agree.  My original idea was to only use file(xxx), but one
>>> constraint
>>> > is to have a different type for consumers and producers because they
>>> have
>>> > different options, so we can't use the same method name.  So the
>>> current
>>> > design is a fallback because I haven't found anything better, but I'm
>>> open
>>> > to suggestions ...
>>> >
>>> >
>>> >
>>> >> My 2 cents,
>>> >> Alex
>>> >>
>>> >>
>>> >>
>>> >> On Tue, Jun 11, 2019 at 7:39 PM Guillaume Nodet <gno...@apache.org>
>>> wrote:
>>> >>
>>> >>> I think I'm done with a first usable pass at the endpoint DSL.
>>> >>> I've removed the getters/setters, added 2 flavors of fluent methods
>>> (one
>>> >>> with the real java type, another one with a String to allow
>>> references
>>> >> and
>>> >>> property placeholder processing), renamed the generated classes to
>>> >>> XxxEndpointBuilder and cleaned things a bit.
>>> >>> In order to access this API, one would create an EndpointRouteBuilder
>>> >>> anonymous class instead of the usual RouteBuilder (see below).  The
>>> only
>>> >>> difference is that it gives immediate access to the fromXxx() and
>>> toXxx()
>>> >>> methods that are generated as default methods on the interface, so
>>> >> there's
>>> >>> no need to import anything else.
>>> >>> Please have a look and let me know what you think or if we see
>>> anything
>>> >> to
>>> >>> improve.
>>> >>>
>>> >>> Cheers,
>>> >>> Guillaume
>>> >>>
>>> >>> protected RouteBuilder createRouteBuilder() throws Exception {
>>> >>>      return new EndpointRouteBuilder() {
>>> >>>          @Override
>>> >>>          public void configure() throws Exception {
>>> >>>
>>> from(fromFile(start).initialDelay(0).delay(10).move(done +
>>> >>> "/${file:name}"))
>>> >>>                      .to(toMock("result"));
>>> >>>          }
>>> >>>      };
>>> >>> }
>>> >>>
>>> >>>
>>> >>> Le mer. 5 juin 2019 à 23:23, Guillaume Nodet <gno...@apache.org> a
>>> >> écrit :
>>> >>>> I just pushed a branch called "endpoint-dsl".
>>> >>>>
>>> >>>> My goal is to experiment with an auto-generated DSL for endpoints,
>>> >> mainly
>>> >>>> to have a complete and type-safe java DSL for endpoints instead of
>>> >> using
>>> >>>> URI containing all the parameters.  Right now, it compiles but isn't
>>> >>> really
>>> >>>> usable at a DSL.
>>> >>>> I'll get back as soon as I have something which can actually be
>>> used so
>>> >>>> that we can discuss further various options.
>>> >>>> My rough goal is to be able to write something like:
>>> >>>>
>>> >>>>     from(file("target/data/foo").delay(4000).backoffMultiplier(4
>>> >>>> ).backoffIdleThreshold(2).backoffErrorThreshold(3))
>>> >>>>        .to(mock("result"))
>>> >>>>
>>> >>>> instead of
>>> >>>>
>>> >>>>     from(
>>> >>>>
>>> >>
>>> "file://target/data/foo?delay=4000&backoffMultiplier=4&backoffIdleThreshold=2&backoffErrorThreshold=3"
>>> >>>> )
>>> >>>>        .to("mock:result")
>>> >>>>
>>> >>>> Stay tuned !
>>> >>>>
>>> >>>> --
>>> >>>> ------------------------
>>> >>>> Guillaume Nodet
>>> >>>>
>>> >>>>
>>> >>> --
>>> >>> ------------------------
>>> >>> Guillaume Nodet
>>> >>>
>>> >
>>>
>>>
>>
>> --
>> ------------------------
>> Guillaume Nodet
>>
>>
>
> --
> ------------------------
> Guillaume Nodet
>
>

-- 
------------------------
Guillaume Nodet

Reply via email to