org.bonitasoft.engine.business.data.generator.RelationFieldAnnotator.java Source code

Java tutorial

Introduction

Here is the source code for org.bonitasoft.engine.business.data.generator.RelationFieldAnnotator.java

Source

/**
 * Copyright (C) 2015 BonitaSoft S.A.
 * BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble
 * This library 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
 * version 2.1 of the License.
 * This library 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 Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301, USA.
 **/
package org.bonitasoft.engine.business.data.generator;

import static org.apache.commons.lang3.StringUtils.left;

import javax.persistence.CascadeType;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.OrderColumn;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.sun.codemodel.JAnnotationArrayMember;
import com.sun.codemodel.JAnnotationUse;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JFieldVar;
import org.bonitasoft.engine.bdm.model.field.RelationField;
import org.bonitasoft.engine.bdm.model.field.RelationField.Type;

/**
 * @author Colin PUY
 */
public class RelationFieldAnnotator {

    private final CodeGenerator codeGenerator;

    private final ForeignKeyAnnotator foreignKeyAnnotator;

    public RelationFieldAnnotator(final CodeGenerator codeGenerator) {
        this.codeGenerator = codeGenerator;
        this.foreignKeyAnnotator = new ForeignKeyAnnotator(codeGenerator);
    }

    public void annotateRelationField(final JDefinedClass entityClass, final RelationField field,
            final JFieldVar fieldVar) {
        JAnnotationUse relation = null;
        if (field.isCollection()) {
            relation = annotateMultipleReference(entityClass, field, fieldVar);
        } else {
            relation = annotateSingleReference(entityClass, field, fieldVar);
        }

        if (field.isLazy()) {
            relation.param("fetch", FetchType.LAZY);
            codeGenerator.addAnnotation(fieldVar, JsonIgnore.class);
        } else {
            relation.param("fetch", FetchType.EAGER);
        }

        if (field.getType() == Type.COMPOSITION) {
            relation.param("cascade", CascadeType.ALL);
        } else if (field.getType() == Type.AGGREGATION) {
            relation.param("cascade", CascadeType.MERGE);
        }

    }

    private JAnnotationUse annotateSingleReference(JDefinedClass entityClass, final RelationField field,
            final JFieldVar fieldVar) {
        JAnnotationUse relation;
        if (field.getType() == Type.AGGREGATION) {
            relation = codeGenerator.addAnnotation(fieldVar, ManyToOne.class);
        } else {
            relation = codeGenerator.addAnnotation(fieldVar, OneToOne.class);
            relation.param("orphanRemoval", true);
        }
        addJoinColumn(fieldVar, field.getName());
        relation.param("optional", field.isNullable());
        foreignKeyAnnotator.annotateForeignKeyName(entityClass, fieldVar, field);
        return relation;
    }

    private JAnnotationUse annotateMultipleReference(final JDefinedClass entityClass, final RelationField field,
            final JFieldVar fieldVar) {
        JAnnotationUse relation;
        if (field.getType() == Type.AGGREGATION) {
            relation = codeGenerator.addAnnotation(fieldVar, ManyToMany.class);
            addJoinTable(entityClass, field, fieldVar);

        } else {
            relation = codeGenerator.addAnnotation(fieldVar, OneToMany.class);
            relation.param("orphanRemoval", true);
            final JAnnotationUse joinColumn = addJoinColumn(fieldVar, entityClass.name());
            joinColumn.param("nullable", false);
        }
        codeGenerator.addAnnotation(fieldVar, OrderColumn.class);
        return relation;
    }

    private void addJoinTable(final JDefinedClass entityClass, final RelationField field,
            final JFieldVar fieldVar) {
        final JAnnotationUse joinTable = codeGenerator.addAnnotation(fieldVar, JoinTable.class);
        joinTable.param("name", getJoinTableName(entityClass.name(), field.getName()));

        final JAnnotationArrayMember joinColumns = joinTable.paramArray("joinColumns");
        final JAnnotationUse nameQueryAnnotation = joinColumns.annotate(JoinColumn.class);
        nameQueryAnnotation.param("name", getJoinColumnName(entityClass.name()));

        final JAnnotationArrayMember inverseJoinColumns = joinTable.paramArray("inverseJoinColumns");
        final JAnnotationUse a = inverseJoinColumns.annotate(JoinColumn.class);
        a.param("name", getJoinColumnName(field.getReference().getSimpleName()));
    }

    private JAnnotationUse addJoinColumn(final JFieldVar fieldVar, final String columnName) {
        final JAnnotationUse joinColumn = codeGenerator.addAnnotation(fieldVar, JoinColumn.class);
        joinColumn.param("name", getJoinColumnName(columnName));
        return joinColumn;
    }

    /**
     * Split names to 26 char to avoid joinColumn names longer than 30 char
     * protected for testing
     */
    protected String getJoinColumnName(final String entityName) {
        return left(entityName.toUpperCase(), 26) + "_PID";
    }

    /**
     * Split names to 14 chars max to avoid joinTable names longer than 30 char (oracle restriction).
     * protected for testing
     */
    protected String getJoinTableName(final String entityName, final String relatedEntityName) {
        final String name = left(entityName.toUpperCase(), 14);
        final String refName = left(relatedEntityName.toUpperCase(), 14);
        return name + "_" + refName;
    }
}