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