2013/9/21 Lukas Eder <[email protected]> > > 2013/9/21 Stéphane Cl <[email protected]> > >> Hi Lukas, >> >> Le samedi 21 septembre 2013 11:03:04 UTC+2, Lukas Eder a écrit : >>> >>> Hi Stéphane, >>> >>> Thanks a lot for taking the time and sharing your insight. >>> >>> 2013/9/20 Stéphane Cl <[email protected]> >>> >>> The documentation is quite good actually, except for the custom >>>> generator ... >>>> I admit I may not be the smartest guy out there but I could not guess >>>> that I needed to override getJavaIdentifier in order to decide the static >>>> names of both table and fields without a bunch of println and debugging. A >>>> fairly large number of different things can be called "Identifiers" in >>>> programming. >>>> >>> >>> Good point, I see what you mean. I guess that a couple of example files >>> could be listed with comments about how each artefact is generated. E.g. >>> >>> package org.jooq.test.h2.generatedclasses.tables; >>> // strategy.getJavaPackageName(table) >>> >>> >>> public class TAuthor extends >>> org.jooq.impl.TableImpl<org.jooq.test.h2.generatedclasses.tables.records.TAuthorRecord> >>> { >>> // 1 ^^^^^ >>> 2 ^^^^^^^^^^^ >>> // 1: strategy.getJavaClassName(table) >>> >>> // 2: strategy.getJavaClassName(table, Mode.RECORD) >>> >>> public static final org.jooq.test.h2.generatedclasses.tables.TAuthor >>> T_AUTHOR = new org.jooq.test.h2.generatedclasses.tables.TAuthor(); >>> 3 ^^^ -> <- >>> ^^^^^ 4 ^^^^^^ >>> >>> // 3: strategy.getFullJavaClassName(table) >>> >>> // 4: strategy.getJavaIdentifier(table) >>> >>> >>> What would you think of this? >>> >>> >> That would have saved me many hours... >> > > OK, that should be rather easy to fix. Should be included in jOOQ 3.2, by > the end of September: > https://github.com/jOOQ/jOOQ/issues/2761 > > >> >> >>> Finding out that I can instanceof the Definition parameter to know if >>>> we are talking about a field, a table or whatever isn't an easy guess >>>> either (in my first attempts, I relied to the number of dots in the >>>> qualified name to know it). >>>> >>> >>> True, that would be easy to document. >>> >>> >>>> Also, I expected to be able to set the java property name of a record >>>> field without relying to [get/set]javaGetterName which seemed to be there >>>> only in case you wouldn't want to follow the normal javabean naming >>>> convention. >>>> >>> >>> I'm not sure I understand this. Property names are generated from >>> strategy.getJavaMemberName(), which works independently from >>> getJavaGetterName() and getJavaSetterName(). >>> >>> >> >> That's an error from me, I thought you had to use getJava[G/S]etterName >> to decide the name of the your record field in the visible API. Glad to >> know there is a better way. >> >> >>> Also, it's not very intuitive to me that I need to override >>>> getJavaClassName and watch for mode=DEFAULT to set the Table class name, >>>> mode=RECORD to set the record name, I discovered it by debugging, before >>>> that I was asking myself why those methods were called hundreds of times >>>> and how I could modify them without interfering with the multiple other >>>> possible scenarios. >>>> >>> >>> True. The Mode.DEFAULT mode is a bit confusing. It would be better if >>> there was no DEFAULT mode, but only explicit modes. The rationale behind >>> default is the fact that tables, arrays, udts can render in: >>> >>> - DEFAULT mode (i.e. meta object) >>> - RECORD mode >>> - INTERFACE mode (currently only tables) >>> - DAO mode (currently only tables) >>> - POJO mode (currently only tables) >>> >>> The fact that most modes only apply to tables shows that the "Mode >>> generalisation" might've been a bit premature when it was added. >>> >>> It would have been so much easier if there had been distinct methods for >>>> generating record class names, table class names, table static identifiers, >>>> fields static identifiers or field property names with clear purpose and >>>> meaningful names, in that case I admit the current documentation would be >>>> sufficient. >>>> >>> >>> That's another option... >>> >>> >> >> And I think it is among the best ones ;-). Doesn't break compatibility, >> self documenting and and doesn't require much work. >> > > OK, I think that can be aligned with the newly suggested XML I've > mentioned further down. Another one for jOOQ 3.2, hopefully: > https://github.com/jOOQ/jOOQ/issues/2762 > > >> >> >>> However, the documentation doesn't give you many hints when you need >>>> anything more specific than a typical "lowecase all, prefix all". Remember >>>> that people writing their first generator are not necessarily Jooq experts, >>>> they probably just want to override a few names that didn't come out clean >>>> and honestly I am sure such a task doesn't have to be that complicated. >>>> >>> >>> Yes. That sort of task will be covered by the XML based generator. This >>> naming strategy SPI is really targeted for "jOOQ experts" and should be the >>> basis for all other naming tools. >>> >>> >>>> Perhaps, after all, the solution is as described above : add a subclass >>>> of DefaultGeneratorStrategy that delegates to simpler methods with >>>> meaningful names and parameters? >>>> Otherwise, I think it would be helpful to document the generator >>>> methods and better explain the different scenarios in which they are >>>> called. >>>> >>>> Other than that, I thought about contributing a basic XML based >>>> generator with some syntax like >>>> >>>> <table name="wa_authors"> >>>> <class>Authors</class> >>>> <record>AuthorRecord</record> >>>> <staticidentifier>T_AUTHORS</staticidentifier> >>>> <fields> >>>> <field name="idauthor" property="idAuthor"> >>>> <...> >>>> </fields> >>>> </table> >>>> >>> >>> Then, we'll need an additional XML generator to generate these >>> configuration files :-) >>> >>> >> Not sure... You would only declare table or fields that don't come out >> right, in my case it's about 20% of the DB objects. The rest would be left >> to the default strategies. >> > > From my experience with the jOOQ User Group, it's much more than 20% for > some users. Think about custom prefixes / postfixes, etc. Or about removing > jOOQ's camel-casing transformation for classes / upper-casing > transformation for identifiers (common among SQL Server users). > > In that case, one static configuration per table becomes prohibitive. > > >> >> >>> On a more serious note: >>> It would work, of course. The good thing about this suggestion is the >>> fact that it maps quite directly to the current GeneratorStrategy API. The >>> bad thing is that it might be a bit hard to maintain on the user side >>> without pattern matching capabilities. If your idea was combined with >>> what's documented in #1171 (https://github.com/jOOQ/jOOQ/issues/1171), >>> we could get something along the lines of: >>> >>> <match type="table" name="(.*?)\.wa_(.*?)"> >>> >>> <table-package transform="lower-case" >>> >com.example.tables.$1</table-package> >>> >>> <table-class transform="camel-case">$2</table-class> >>> >>> <table-identifier transform="upper-case">$2</table-identifier> >>> >>> <table-implements>com.example.MyInterface, >>> com.example.MyOtherInterface<table-implements> >>> >>> <record-package >>> transform="lower-case">com.example.records.$1</record-package> >>> >>> <record-class transform="camel-case">$2Record</record-class> >>> >>> <interface-class>...</interface-class> >>> >>> <dao-class>...</dao-class> >>> >>> <pojo-class>...</pojo-class> >>> >>> </match> >>> >>> <match type="field" name=".*?\.wa_.*?\.(.*?)> >>> >>> <field-identifier transform="upper-case">$1<table-field-identifier> >>> >>> <field-member transform="camel-case">$1</field-member> >>> >>> <field-setter transform="camel-case">set_$1</table-field-setter> >>> >>> <field-getter transform="camel-case">get_$1</table-field-getter> >>> >>> </match> >>> >>> <match type="routine">...</match> >>> >>> >>> The transform attribute would allow for these values: "as-is" (default), >>> "upper-case", "lower-case", "camel-case", "pascal-case". Regex pros could >>> also try to implement their own rules. >>> >>> What I like about the combination of pattern matching and your >>> suggestion is the fact that: >>> >>> - It is very generic, allowing for arbitrary overriding of jOOQ's >>> default behaviour. >>> - It is quite easy to understand and maintain at the user side. >>> - It is XML-based, and thus easy to document and formalise through XSD. >>> - It largely removes hard-wired ideas / features such as prefixes, >>> suffixes, etc as those can be very easily implemented using pattern >>> matching and replacement. >>> >>> To me, this starts to sound like a good feature covering pretty much all >>> code generation customisation needs for the next 1-2 years. What do you >>> think? >>> >>> >> Here again, the important thing to note is that you probably don't want >> to set particular rules for every single objects, only the few ones that >> don't come out right with the default naming scheme. >> > > Again, *you* want that. :-) Others want to control naming of *all* objects > > >> Your proposition sounds good to me because you could define a generic >> default naming convention that would be fine for 80% of your particular DB >> objects and switch to table of field level when needed which is probably >> what most people need. >> > > Hmm, maybe I didn't stress enough the fact that the above XML > configuration will apply only when it matches. When it doesn't match, > jOOQ's defaults will apply. In other words, your use case is fully covered > by my alternative. You can provide an exact regex matching only one table > and then rename all objects for precisely that table. Except that you can > also match more than one table, if so desired. > > Does that make sense? >
A first draft is committed to GitHub and integration tested with the H2 database. Details here: https://github.com/jOOQ/jOOQ/issues/1171 This was actually surprisingly easy to implement with the existing GeneratorStrategy as can be seen in the new MatcherStrategy: https://github.com/jOOQ/jOOQ/blob/1a4ce84c4ae2b8810faa2b4178a74835860cf071/jOOQ-codegen/src/main/java/org/jooq/util/MatcherStrategy.java The MatcherStrategy applies automatically, when someone configures the <strategy> element with a <matchers> element. Of course, this will be nicely documented with examples ;-) Early reviews / feedbacks welcome Cheers Lukas -- You received this message because you are subscribed to the Google Groups "jOOQ User Group" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/groups/opt_out.
