Fork me on GitHub

Rades Annotations Projekt

Dieses Projekt stellt Annotationen nebst zugehörigen Annotation Prozessoren bereit. Sobald das ausgelieferte Projektarchiv (JAR) im Klassenpfad Ihrer Anwendung eingebunden ist, können Sie die Annotationen benutzen.

Download des Projektarchives

Manueller Download

Sie können das Produkt über Ihren Webbroser manuell von der JFrog Seite herunterladen.

Download per Mavenintegration

(Dieser Schritt ist optional seit das Projekt auch über Maven Central verfügbar ist)

Da das Projekt dankenswerter Weise von JFrog ins JCenter aufgenommen wurde, wird kein spezieller Download Link benötigt, sondern es genügt die Integration des JCenters in Maven als Downloadquelle.

pom.xml
<repositories>
    <repository>  (1)
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
        <id>central</id>
        <name>bintray</name>
        <url>https://jcenter.bintray.com</url> (3)
    </repository>
</repositories>
:
<dependencies>
    <dependency>  (2)
        <groupId>com.github.funthomas424242</groupId>
        <artifactId>rades-annotations</artifactId>
        <version>3.0.0</version>
    </dependency>
</dependencies>
1 Definition des Repositories.
2 Definition der Projektabhängigkeit.
3 Das ist der eigentliche Download URL des JCenter.

Benutzung der Annotationen

Person.java
import com.github.funthomas424242.rades.annotations.builder.RadesAddBuilder;

@RadesAddBuilder
public class Person {
:
}

Das Generat

Die @RadesAddBuilder bzw. die @AddBuilder Annotationen können synonym verwendet werden, sie nutzen den selben Annotationsprozessor. Die verschiedenen Schreibweisen bilden lediglich eine Auswahl für den Entwickler um die Lesbarkeit seines Programmkodes verbessern zu können - für den Fall, dass noch weitere Annotationsframeworks zum Einsatz kommen.

Die Annotationen erzeugen eine Javaklasse welche den Namen des annotierten Elements trägt, erweitert um den Suffix "Builder". Obiger Kode würde also zur Generierung der Klasse PersonBuilder führen. Diese Klasse wird im gleichen Package wie die annotierte Klasse Person liegen. Letzteres ist erforderlich um über Java Bordmitel Zugriff auf die Attribute der annotierten Klasse Person zu erhalten.

private Attribute werden vom generierten Builder nicht unterstützt.

Beispiele

Builder und Accessor für Person (@RadesAddBuilder, @RadesAddAccessor)

Person.java
package com.github.funthomas424242.domain;

/*-
 * #%L
 * rades-annotations
 * %%
 * Copyright (C) 2018 PIUG
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
 * #L%
 */

import com.github.funthomas424242.rades.annotations.accessors.NoAccessor;
import com.github.funthomas424242.rades.annotations.accessors.RadesAddAccessor;
import com.github.funthomas424242.rades.annotations.accessors.RadesNoAccessor;
import com.github.funthomas424242.rades.annotations.builder.NoBuilder;
import com.github.funthomas424242.rades.annotations.builder.RadesAddBuilder;
import com.github.funthomas424242.rades.annotations.builder.RadesNoBuilder;

import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.Period;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;


@RadesAddBuilder
@RadesAddAccessor
public class Person {

    public enum Farbe {
        ROT,
        GELB,
        GRÜN,
        BLAU,
        LILA,
        SCHWARZ,
        BRAUN,
        WEISS
    }

    private int id;

    @NotNull
    protected String name;

    // check for package scope
    String vorname;

    protected LocalDate birthday;

    public int groesse;

    @RadesNoAccessor
    @RadesNoBuilder
    @NotNull
    protected final Set<Farbe> lieblingsfarben = new HashSet<>();

    @NoAccessor
    @NoBuilder
    @NotNull
    protected Map<String, Person> freunde = new HashMap<>();


    protected Map<String, LocalDate> visitedPlaces = new HashMap<>();


    public int getId() {
        return id;
    }

    public void setId(final int id) {
        this.id = id;
    }

    public int computeAge() {
        if (this.birthday == null) {
            throw new IllegalStateException("birthday is unknow because is jet not set");
        }
        final Period period = birthday.until(LocalDate.now());
        return period.getYears();
    }

    public Stream<Farbe> getLieblingsfarben() {
        return this.lieblingsfarben.stream();
    }

    public void addLieblingsfarbe(final Farbe farbe) {

        this.lieblingsfarben.add(farbe);
    }

    public void removeLieblingsfarbe(final Farbe farbe) {
        this.lieblingsfarben.remove(farbe);
    }

    public void addFreund(final String alias, final Person freund) {
        this.freunde.put(alias, freund);
    }

    @Override
    public String toString() {
        return name + ", " + vorname;
    }
}

Aus dieser Domain Klasse ensteht folgender Builder

PersonBuilder.java
package com.github.funthomas424242.domain;

import com.github.funthomas424242.rades.annotations.accessors.InvalidAccessorException;
import javax.annotation.Generated;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

@Generated(value="RadesBuilderProcessor"
, date="2018-04-06T20:36:46.750"
, comments="com.github.funthomas424242.domain.Person")
public class PersonBuilder {

    private Person person;

    public PersonBuilder(){
        this(new Person());
    }

    public PersonBuilder( final Person person ){
        this.person = person;
    }

    public Person build() {
        final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        final java.util.Set<ConstraintViolation<Person>> constraintViolations = validator.validate(this.person);

        if (constraintViolations.size() > 0) {
            java.util.Set<String> violationMessages = new java.util.HashSet<String>();

            for (ConstraintViolation<?> constraintViolation : constraintViolations) {
                violationMessages.add(constraintViolation.getPropertyPath() + ": " + constraintViolation.getMessage());
            }

            final StringBuffer buf = new StringBuffer();
            buf.append("Person is not valid:\n");
            violationMessages.forEach(message -> buf.append(message + "\n"));
            throw new ValidationException(buf.toString());
        }
        final Person value = this.person;
        this.person = null;
        return value;
    }

    public <A> A build(Class<A> accessorClass) {
        final Person person = this.build();
        this.person=person;
        try{
            final Constructor<A> constructor=accessorClass.getDeclaredConstructor(Person.class);
            final A accessor = constructor.newInstance(person);
            this.person=null;
            return accessor;
        }catch(NoSuchMethodException | IllegalAccessException|  InstantiationException|  InvocationTargetException ex){
            throw new InvalidAccessorException("ungültige Accessorklasse übergeben",ex);
        }
    }

    public PersonBuilder withBirthday( final java.time.LocalDate birthday ) {
        this.person.birthday = birthday;
        return this;
    }

    public PersonBuilder withVisitedPlaces( final java.util.Map<java.lang.String,java.time.LocalDate> visitedPlaces ) {
        this.person.visitedPlaces = visitedPlaces;
        return this;
    }

    public PersonBuilder withGroesse( final int groesse ) {
        this.person.groesse = groesse;
        return this;
    }

    public PersonBuilder withName( final java.lang.String name ) {
        this.person.name = name;
        return this;
    }

    public PersonBuilder withVorname( final java.lang.String vorname ) {
        this.person.vorname = vorname;
        return this;
    }

}

und folgender Accessor

PersonAccessor.java
package com.github.funthomas424242.domain;

import javax.annotation.Generated;
@Generated(value="RadesAccessorProcessor"
, date="2018-04-06T20:36:46.750"
, comments="com.github.funthomas424242.domain.Person")
public class PersonAccessor {
    protected final Person person;
    public PersonAccessor( final Person person ){
        this.person = person;
    }
    public Person toPerson(){
        return this.person;
    }

    public java.util.stream.Stream<com.github.funthomas424242.domain.Person.Farbe> getLieblingsfarben(){
        return this.person.getLieblingsfarben();
    }

    public java.lang.String toString(){
        return this.person.toString();
    }

    public int getId(){
        return this.person.getId();
    }

    public void addFreund(final java.lang.String alias, final com.github.funthomas424242.domain.Person freund){
        this.person.addFreund(alias, freund);
    }

    public java.lang.String getVorname( ) {
        return this.person.vorname;
    }

    public void setId(final int id){
        this.person.setId(id);
    }

    public int computeAge(){
        return this.person.computeAge();
    }
    public void removeLieblingsfarbe(final com.github.funthomas424242.domain.Person.Farbe farbe){
        this.person.removeLieblingsfarbe(farbe);
    }

    public java.time.LocalDate getBirthday( ) {
        return this.person.birthday;
    }

    public void addLieblingsfarbe(final com.github.funthomas424242.domain.Person.Farbe farbe){
        this.person.addLieblingsfarbe(farbe);
    }

    public java.util.Map<java.lang.String,java.time.LocalDate> getVisitedPlaces( ) {
        return this.person.visitedPlaces;
    }

    public int getGroesse( ) {
        return this.person.groesse;
    }

    public java.lang.String getName( ) {
        return this.person.name;
    }
}

Builder und Accessor für Firma (@AddBuilder, @AddAccessor)

Firma.java
package com.github.funthomas424242.domain;

/*-
 * #%L
 * rades-annotations
 * %%
 * Copyright (C) 2018 PIUG
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
 * #L%
 */

import com.github.funthomas424242.rades.annotations.accessors.AddAccessor;
import com.github.funthomas424242.rades.annotations.accessors.RadesAddAccessor;
import com.github.funthomas424242.rades.annotations.builder.AddBuilder;
import com.github.funthomas424242.rades.annotations.builder.RadesAddBuilder;

import java.util.Date;

@RadesAddBuilder
@AddBuilder(simpleBuilderClassName = "FirmaAGErbauer")
@RadesAddAccessor
@AddAccessor(simpleAccessorClassName =  "FirmaAGZugreifer")
public class Firma {

    private int id;

    protected String name;

    protected String betriebeNr;

    protected Date gruendungstag;

    public int getId() {
        return id;
    }

    public void setId(final int id) {
        this.id = id;
    }

}

Aus dieser Domain Klasse ensteht folgender Builder

FirmaAGErbauer.java
package com.github.funthomas424242.domain;

import com.github.funthomas424242.rades.annotations.accessors.InvalidAccessorException;
import javax.annotation.Generated;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

@Generated(value="RadesBuilderProcessor"
, date="2018-04-06T20:36:46.750"
, comments="com.github.funthomas424242.domain.Firma")
public class FirmaAGErbauer {

    private Firma firma;

    public FirmaAGErbauer(){
        this(new Firma());
    }

    public FirmaAGErbauer( final Firma firma ){
        this.firma = firma;
    }

    public Firma build() {
        final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        final java.util.Set<ConstraintViolation<Firma>> constraintViolations = validator.validate(this.firma);

        if (constraintViolations.size() > 0) {
            java.util.Set<String> violationMessages = new java.util.HashSet<String>();

            for (ConstraintViolation<?> constraintViolation : constraintViolations) {
                violationMessages.add(constraintViolation.getPropertyPath() + ": " + constraintViolation.getMessage());
            }

            final StringBuffer buf = new StringBuffer();
            buf.append("Firma is not valid:\n");
            violationMessages.forEach(message -> buf.append(message + "\n"));
            throw new ValidationException(buf.toString());
        }
        final Firma value = this.firma;
        this.firma = null;
        return value;
    }

    public <A> A build(Class<A> accessorClass) {
        final Firma firma = this.build();
        this.firma=firma;
        try{
            final Constructor<A> constructor=accessorClass.getDeclaredConstructor(Firma.class);
            final A accessor = constructor.newInstance(firma);
            this.firma=null;
            return accessor;
        }catch(NoSuchMethodException | IllegalAccessException|  InstantiationException|  InvocationTargetException ex){
            throw new InvalidAccessorException("ungültige Accessorklasse übergeben",ex);
        }
    }

    public FirmaAGErbauer withGruendungstag( final java.util.Date gruendungstag ) {
        this.firma.gruendungstag = gruendungstag;
        return this;
    }

    public FirmaAGErbauer withBetriebeNr( final java.lang.String betriebeNr ) {
        this.firma.betriebeNr = betriebeNr;
        return this;
    }

    public FirmaAGErbauer withName( final java.lang.String name ) {
        this.firma.name = name;
        return this;
    }

}

und folgender Accessor

FirmaAGZugreifer.java
package com.github.funthomas424242.domain;

import javax.annotation.Generated;

@Generated(value="RadesAccessorProcessor"
, date="2018-04-06T20:36:46.750"
, comments="com.github.funthomas424242.domain.Firma")
public class FirmaAGZugreifer {

    protected final Firma firma;

    public FirmaAGZugreifer( final Firma firma ){
        this.firma = firma;
    }

    public Firma toFirma(){
        return this.firma;
    }

    public java.util.Date getGruendungstag( ) {
        return this.firma.gruendungstag;
    }

    public void setId(final int id){
        this.firma.setId(id);
    }

    public java.lang.String getBetriebeNr( ) {
        return this.firma.betriebeNr;
    }

    public int getId(){
        return this.firma.getId();
    }

    public java.lang.String getName( ) {
        return this.firma.name;
    }

}