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?

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().


> 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...


> 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 :-)

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?

I had a few other ideas, like for example delegating generator methods to a
> dynamically loaded groovy script to declare a default name conversion
> scheme.
> However I did not dig the idea too much because I thought the generator
> was going to be rewritten from scratch.
>

I think there is no perfect solution to a code generator. Even XJC for
XML/JAXB is rather awkward to use when you want to highly customise your
generated Java code. Aaron Digulla had started to tackle this improvement
task using an Xtend-based code generator:
https://groups.google.com/d/msg/jooq-user/yydHOYcbPrQ/sNYYI4lYcG0J

This also resulted in rewriting the whole thing from scratch, which did not
align with maintenance interests at the time. Though, I have started to
really like the idea behind Xtend for code generation.

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.

Reply via email to