All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.heliorm.mojo.annotated.AnnotatedPojoTable Maven / Gradle / Ivy

There is a newer version: 0.99.107
Show newest version
package com.heliorm.mojo.annotated;

import com.heliorm.Database;
import com.heliorm.Field;
import com.heliorm.Index;
import com.heliorm.Table;
import com.heliorm.annotation.Ignore;
import com.heliorm.annotation.Pojo;

import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
 * Implementation of Table that is build from POJO annotations.
 *
 * @author gideon
 */
public final class AnnotatedPojoTable implements Table {

    private final Database database;
    private final Class pojoClass;
    private final Set subs;
    private List fieldModels;
    private List indexes;

    /**
     * Create a new table with the given database, POJO class and set of
     * sub-tables.
     *
     * @param database  The database
     * @param pojoClass The POJO class
     * @param subTables The set of sub-tables
     */
    public AnnotatedPojoTable(Database database, Class pojoClass, Set subTables) {
        this.database = database;
        this.pojoClass = pojoClass;
        this.subs = unrollSubTables(subTables);
    }

    @Override
    public String getSqlTable() {
        Optional pojo = getAnnotation(Pojo.class);
        if (pojo.isPresent()) {
            if (!pojo.get().tableName().isEmpty()) {
                return pojo.get().tableName();
            }
        }
        return getJavaName();
    }

    @Override
    public List getFields() {
        if (fieldModels == null) {
            List fields = getAllFields(pojoClass);
            fieldModels = new ArrayList<>();
            for (java.lang.reflect.Field field : fields) {
                if (isDataField(field)) {
                    fieldModels.add(new AnnotatedPojoField(this, field));
                }
            }
        }
        return fieldModels;
    }

    @Override
    public Optional getPrimaryKey() {
        return getFields().stream().filter(Field::isPrimaryKey).findAny();
    }

    @Override
    public Database getDatabase() {
        return database;
    }

    @Override
    public Class getObjectClass() {
        return pojoClass;
    }

    @Override
    public Set
getSubTables() { return new HashSet<>(subs); } @Override public boolean isAbstract() { return Modifier.isAbstract(pojoClass.getModifiers()); } @Override public boolean isRecord() { return pojoClass.isRecord(); } @Override public List getIndexes() { if (indexes == null) { indexes = new ArrayList<>(); List anns = getAnnotations(com.heliorm.annotation.Index.class); for (com.heliorm.annotation.Index ann : anns) { indexes.add(new AnnotatedPojoIndex(this, ann)); } } return indexes; } /** * Decide if a reflected field is a data field we need to process. A field * is considered a POJO field if it is not native, not transient, not static * and not annotated with the @Ignore annotation. * * @param field The reflected field to evaluate * @return True if it is considered a data field */ private boolean isDataField(java.lang.reflect.Field field) { int modifiers = field.getModifiers(); if (Modifier.isNative(modifiers)) { return false; } if (Modifier.isTransient(modifiers)) { return false; } if (Modifier.isStatic(modifiers)) { return false; } return !field.isAnnotationPresent(Ignore.class); } /** * Return the Java name for the POJO class represented by this * * @return The Java name */ private String getJavaName() { return pojoClass.getSimpleName(); } /** * Convenience method to find the optional annotation on the POJO class. * * @param The type of the annotation * @param annotationClass The annotation class * @return Optional annotation found */ private Optional getAnnotation(Class annotationClass) { return Optional.ofNullable(pojoClass.getAnnotation(annotationClass)); } private List getAnnotations(Class annotationClass) { Class target = pojoClass; List annotations = new ArrayList<>(); while (!Object.class.equals(target)) { T[] found = target.getAnnotationsByType(annotationClass); annotations.addAll(Arrays.asList(found)); target = target.getSuperclass(); } return annotations; } /** * Return reflected fields for all fields declared on a class and it's super * classes but stopping short of java.lang.Object (recursively) * * @param clazz The class to return the fields from * @return The list of fields */ private List getAllFields(Class clazz) { List res = new LinkedList<>(); if (clazz.getSuperclass() != Object.class) { res.addAll(getAllFields(clazz.getSuperclass())); } res.addAll(Arrays.asList(clazz.getDeclaredFields())); return res; } private Set
unrollSubTables(Set subs) { Set
res = new HashSet<>(); for (Table sub : subs) { if (!sub.isAbstract()) { res.add(sub); } res.addAll(unrollSubTables(sub.getSubTables())); } return res; } }