GithubHelp home page GithubHelp logo

sporniket / javabeans Goto Github PK

View Code? Open in Web Editor NEW
0.0 2.0 1.0 651 KB

A project to convert Java POJO structures into Javabeans replicating the class hierarchy a.k.a. "Yet Another Javabeans Generator".

License: GNU Lesser General Public License v3.0

Java 99.97% Groovy 0.03%
java-bean java code-generator javabeans doclet javabeans-generator jpa-hibernate

javabeans's Issues

FIX windows path backslash problem

When running on windows, the backslash is used to escape characters instead of being used as is.

After processing the command line, replace any backslash by a double backslash.


It seems it is solvable using a groovy script that create a new variable with the expected value, and use it as the target path base :

            <!-- === Groovy hack to support windows pathes === -->
            <plugin>
                <groupId>org.codehaus.groovy.maven</groupId>
                <artifactId>gmaven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>set-unixy_build_directory!</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>execute</goal>
                        </goals>
                        <configuration>
                            <classpath>
                                <element>
                                    <groupId>commons-lang</groupId>
                                    <artifactId>commons-lang</artifactId>
                                    <version>2.4</version>
                                </element>
                            </classpath>
                            <source>
                                project.properties['mybuilddir'] =
                                project.build.directory.replace('\\','/');
                            </source>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!-- === code generation using the doclets === -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <executions>
                    <!-- === Javabeans generation === -->
                    <execution>
                        <!-- ... -->
                        <configuration>
                            <doclet>com.sporniket.libre.javabeans.doclet.ExpanderDoclet</doclet>
                            <!-- ... -->
                            <additionalOptions>
                                <additionalOption>-d</additionalOption>
                                <additionalOption>"${mybuilddir}/generated-classes/javabeans"</additionalOption>
                                <!-- ... -->
                            </additionalOptions>
                            <!-- ... -->
                        </configuration>
                    </execution>
                </executions>
            </plugin>

Support annotation with parameters (esp. some jackson-annotations)

User Story

As sporniket-javabeans-doclet, I want to generate parametrized annotation
So that a developper is able to use jackson-annotations (@JsonProperty, @JsonTypeInfo and @JsonSubTypes)

Detailed Technical Specifications

Parameter name rules

  • The "value" parameter name is omitted, only the parameter value is generated
  • Otherwise the parameter name is generated followed by '=' and the parameter value

Parameter value rules

  • Literral values that are not class names are generated as is.
  • Enum values, constants, are imported to minimize value length.
  • Class names are processed to target generated classes if appliable

Generated classes import native types

When a field has a native type, e.g. boolean, the generated classes will import the native type and trigger a compilation error.

Native types must be removed from the import list.

Generate a fluent Builder in a separate generator instead of generating fluent setters in the Javabeans

The current fluent setter generation has some flaws :

  • it can only generate fluent setters for the attribute directly declared in the class description
  • herited fluent setters breaks the chaining of calls (cannot access to the derived class fluent setters without casting...)
  • add bloat to an already bloated javabean.

Thus It may be more appropriate to remove the fluent api in the generated bean, and to generate a fluent Builder from an existing class, scanned using reflexion :

  • the generator process each class of a designated package (more on that latter)
  • If a class is abstract or is an interface, skip to the next one
  • If the class has no setter ("setXxx(...)"), skip to the next one
  • Generate a builder following the given pattern
public class MaStructureBuilder {
    private MaStructure maStructure = new MaStructure() ;

    public static final MaStructureBuilder builder() {
        return new MaStructureBuilder() ;
    }

    public build() {
        MaStructure result = maStructure ;
        maStructure = new MaStructure() ;
        return result ;
    }

    public void withXxx(XxxType value) {
        maStructure.setXxx(value);
        return this ;
    }

    //etc...
}

The generator will be instructed to scan some class using :

  • a list of specifically targeted classes
  • a list of packages
  • a list of specifically excluded classes
  • a list of regexp to exclude classes matched on their simple name
  • a list of regexp to exclude classse matched on their full name

Allow to override fluent accessor in generated subclass

when generating a fluent accessor in a class, and generating a subclass, using the herited fluent accessor cannot be chained to another fluent accessor of the subclass.

allow something like :

<fluent name="xxx" type="yyy">

The name and type MUST obviously match the original definition for the code to be ok.

Collection/Map event names should be generated litterally

Redefining the suffixes (Foo.__EVENT_SUFFIX__ADD, Foo.__EVENT_SUFFIX__ADD_ALL,...) for use in each generated class is ugly.
Generate the names without using literral instead of storing the prefix in a separate static final field for use when initializing a property name for a managed collection/map event.

Extract javabean modelization and code generation

User story

As a developper

I want to have a separated javabean and builder generation code

In order to generate javabeans from other descriptions than POJO, e.g. from a database schema.

Technical details

  • The exchance format would be the json representation of a collection of ClassSpecs
  • Each generator (pojo, javabean, builder) would be adressable, and would be wrapped in a maven plugin

Generate a generic builder for a generated abstract bean

When the generated javabean is abstract, like :

public abstract class SampleAbstractBean {
    private String mySampleProperty ;
    public String getSampleProperty() { return mySampleProperty ; }
    public void setSampleProperty(String sampleProperty) { mySampleProperty = sampleProperty ; }
}

Instead of prevent generating a Builder, generate a generic builder, like :

public class SampleAbstractBean_Builder<T extends SampleAbstractBean> {
    private T myInstance = new T() ;
    public SampleAbstractBean_Builder<T> withSampleProperty() { 
        T.setSampleProperty(sampleProperty) ; 
        this return; 
    }
    public T done() {
        T result = myInstance ;
        myInstance = new T() ;
        return myInstance ;
    }
}

Refactor code generation to separate data preparation from data injection into a template

For now the code generation mixes code generation using "printf" with computing the values given to those printfs.

In order to use a templating system like velocity, the data computation should result into a data structure containing any values to give to those printfs or the templating system

These "code specifications" will be gathered in a "codespecs" package, and named :

  • ImportSpecs : class name, directly required by javabean (not directly = required by inherited field)
  • AnnotationSpecs
  • JavadocSpecs (extends AnnotationSpecs)
  • ClassSpecs : ImportSpecs, FieldSpecs, AnnotationSpecs
  • FieldSpecs : AnnotationSpecs

Thus each ClassDoc object will result into a ClassSpecs object, that will feeds the code generation.

Support arrays fields

When there is the following declaration :

String[] refFields;

Then there is the following generated code :

    private String[] myRefFields ;

    public String[] getRefFields() {return myRefFields ;}
    public void setRefFields(String[] value) {myRefFields = value;}

Instead of the following generated code :

    private String myRefFields ;

    public String getRefFields() {return myRefFields ;}
    public void setRefFields(String value) {myRefFields = value;}

Accessors are not following CamelCase

in the sample project, the generated code looks like :

package com.sporniket.sample.pojos;

import java.util.Date;
import java.util.List;

public abstract class SampleBasic
{

    private Date date ;
    private List<String> names ;

    public Date getdate() {return this.date ;}
    public void setdate(Date value) {this.date = value;}

    public List<String> getnames() {return this.names ;}
    public void setnames(List<String> value) {this.names = value;}

}

e.g. getdate() should be getDate().

The builder class does not compile, because it expects camel cases accessors.

[Bug] Escape string values for annotations parameters

When a field is annoted with @Pattern("\\d{5}")

Then the generated javabean field must be annoted with @Pattern("\\d{5}") instead of @Pattern("\d{5}")

Workaround

The POJO field is annoted with @Pattern("\\\\d{5}")

[doclet][bug] Cannot use nested parametrized types

Steps to reproduce

  1. Write a FooRaw with the following field : Map<String, List<String>> headers;
  2. The generated code (field, accessors, fluent builders) defines headers as Map<String,List> instead of Map<String, List<String>> headers

[seeg] Have a mapper from Entity to IdClass

When a table has a multi-column primary key, there is an id class.

  • Define a conversion method
//...
@IdClass(/*...*/)
class EntityThing {
  //...  
  public IdOfThing toIdClass() { return new IdOfThing(e.myKeyField1/*, ...*/) ; }
}

[seeg] implements compounded primary keys with @IdClass

When a primary key of an entity is made of several columns,

  • create an id class (IdOf[EntityName])
  • referenced by the entity class with the @javax.persistence.IdClass

An instance of id class will be immutable, and redefine the hashcode and equals using its components.

Allow generating abstract class

when creating a full class hierarchy, the base class cannot be abstract.

  • Add a boolean 'abstract' property to the 'Bean' tag

[bug] Some annotation need to be generated on the accessors too

When a field is annoted like this : @JsonProperty("a_different_name") String altName

Then the generated javabean must have the annotation on the field AND the accessors

In order to get a correct JSON representation. (otherwise we get a field "a_different_name" and "altName")

Technical details

  • A registry of annotations that MUST be copied to the setter
  • A registry of annotations that MUST be copied to the getter
  • A registry of annotations that MUST NOT be copied to the field

Copy javadoc comments - class and fields

Update 2019-09-19

  • While generating javabeans : convert pojo class names into javabeans class names.
  • While extracting pojo : copy as is.
  • field javadoc : copy to field, accessors and the fluent method in the builder class.

Update : in fact, javadoc annotations are not annotations in ClassDoc, look at comments and tags. see https://docs.oracle.com/javase/7/docs/jdk/api/javadoc/doclet/com/sun/javadoc/Doc.html


The javadoc class description is a special case of annotation for two reasons :

  • as a javadoc annotation, special case of annotation
  • as the annotation does not use a '@description' tag

The javadoc class description should be copied "as is" into the generated javabean code.

Further implementation of front controller/session

A kind of front controller and session data are required to implement #11 .

Such controller would :

  • be initialized with a set of xml description files (depending the workflow, i.e. a maven plugin could specify all the xml files of the project), that would constitute the processing session. Especially, one would have an index of any generated classes, to infer inheritance, and required code part to generate.
  • create and initialize any required processor/generator, passing appropriate session data. The lifecycle of processors and generators MUST be formalized.
  • call the processing for each beanset.
  • done

Wrong format for additionnal parameters in demo pom

The value of additionalOptions is not supported in some maven installation (I got a problem with Jenkins)

The value must be a collection of additionnalOption.

E.g. :

<additionalOptions>-d
  ${project.build.directory}/generated-classes/javabeans
-beanFieldPrefix ''</additionalOptions>

Should be rewritten as :

<additionalOptions>
    <additionalOption>-d</additionalOption>
    <additionalOption>"${project.build.directory}/generated-classes/javabeans"</additionalOption>
    <additionalOption>-beanFieldPrefix</additionalOption>
    <additionalOption>""</additionalOption>
</additionalOptions>

As a side effect, the pom will be more legible.

Generate a builder that can handle a subclass

User Story

As a developper, I want to subclass a generated bean to add behaviors/method, and I want to be able to instanciate such enhanced javabeans using the builder, in order to avoid writing manually a duplicate of the generated builder for the base class.

Technical specification

Given the generated javabean A and its builder class A_Builder.

Then a regular javabean would be instancied like that : A myA = new A_Builder().with...()....done();.

Then a subclass B of the javabean would be instancied like that : B myB = (B) new A_Builder(new B()).with...().....done() ;

Copy simple class annotations and simple field annotations

Simple annotations are annotations that have no parameters (e.g. @Deprecated)

When generating javabean or extracting pojo, copy those simple annotations, using the simple name instead of the fully qualified name when possible.

Special case : @Deprecated annotations should be copied on the field, on the getter and on the setter.

[bug][seeg]Generate only enums from the target schema

Use this request to get Postgresql enum values : 

SELECT 
 pg_namespace.nspname as schema,
 pg_type.typname AS enum_type, 
 pg_enum.enumlabel AS enum_value 
FROM pg_type 
JOIN pg_enum ON pg_enum.enumtypid = pg_type.oid 
JOIN pg_namespace ON pg_namespace.oid = pg_type.typnamespace
order by pg_enum.enumtypid, pg_enum.enumsortorder

and filter using the target schema.

Class to process are not filtered against PojoSuffix

While mvn install the next version of the project (see acfd4de), the doclet tried :

Generating javabean null from com.sporniket.libre.javabeans.doclet.codespecs.ImportSpecs_Builder 

The build obviously failed.

The doclet MUST filter out the classes that does not have the pojoSuffix.

Do not add boundable and vetoable support code when not needed

For now, the generated classes contains code for managing bounded and vetoed properties, even if there is none.

  • do not add support for listener/fire event for bounded/vetoed properties if there is none
  • do not add property name if it is not boundable/vetoable

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.