com.khubla.cbean.CBeanType.java Source code

Java tutorial

Introduction

Here is the source code for com.khubla.cbean.CBeanType.java

Source

/*
 * cBean Copyright 2016, Tom Everett <tom@khubla.com>
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU 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 Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.khubla.cbean;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import org.apache.commons.beanutils.PropertyUtilsBean;

import com.khubla.cbean.annotation.Entity;
import com.khubla.cbean.annotation.Id;
import com.khubla.cbean.annotation.Property;
import com.khubla.cbean.annotation.Version;

/**
 * A CBean type contains the metadata for a cBean annotated POJO. Metadata is cached by the class to avoid having to generate it more than once per type.
 *
 * @author tom
 */
public class CBeanType {
    /**
     * CBean types
     */
    private static final HashMap<Class<?>, CBeanType> types = new HashMap<Class<?>, CBeanType>();

    /**
     * static getter for CBeanTypes
     */
    public static CBeanType getCBeanType(Class<?> clazz) throws CBeanException {
        CBeanType cBeanType = types.get(clazz);
        if (null == cBeanType) {
            cBeanType = new CBeanType(clazz);
            types.put(clazz, cBeanType);
        }
        return cBeanType;
    }

    /**
     * getter map
     */
    private final HashMap<String, String> getterMap = new HashMap<String, String>();
    /**
     * setter map
     */
    private final HashMap<String, String> setterMap = new HashMap<String, String>();
    /**
     * clazz
     */
    private final Class<?> clazz;
    /**
     * id field name
     */
    private final Field idField;
    /**
     * version field name
     */
    private final Field versionField;
    /**
     * entity
     */
    private final Entity entity;
    /**
     * persistable fields
     */
    private final Field[] persistableFields;
    /**
     * Id annotation
     */
    private final Id id;
    /**
     * lazy load fields
     */
    private final Field[] lazyLoadFields;

    /**
     * ctor
     */
    public CBeanType(Class<?> clazz) throws CBeanException {
        this.clazz = clazz;
        idField = findIdField();
        versionField = findVersionField();
        id = findId();
        persistableFields = findPersistableFields();
        lazyLoadFields = findLazyLoadFields();
        if (null == idField) {
            throw new CBeanException("Unable to find Id field");
        }
        if ((false == (idField.getType() == String.class)) && (false == (idField.getType() == UUID.class))) {
            throw new CBeanException("@Id field must be a String or UUID");
        }
        entity = getEntity();
        if (null == entity) {
            throw new CBeanException("Unable to find Entity field");
        }
        if ((null != versionField) && (versionField.getType() != Integer.class)) {
            throw new CBeanException("@Version field must be an Integer");
        }
        buildGetterSetterMap();
    }

    /**
     * build the map of getters and setters to properties
     */
    private void buildGetterSetterMap() {
        final PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
        final PropertyDescriptor[] propertyDescriptors = propertyUtilsBean.getPropertyDescriptors(clazz);
        if (null != propertyDescriptors) {
            for (int i = 0; i < propertyDescriptors.length; i++) {
                final PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
                if (null != propertyDescriptor.getReadMethod()) {
                    getterMap.put(propertyDescriptor.getReadMethod().getName(), propertyDescriptor.getName());
                }
                if (null != propertyDescriptor.getWriteMethod()) {
                    setterMap.put(propertyDescriptor.getWriteMethod().getName(), propertyDescriptor.getName());
                }
            }
        }
    }

    /**
     * find id field
     */
    private Id findId() {
        final Field[] fields = clazz.getDeclaredFields();
        if (null != fields) {
            for (int i = 0; i < fields.length; i++) {
                final Field field = fields[i];
                final Id id = field.getAnnotation(Id.class);
                if (null != id) {
                    return id;
                }
            }
        }
        return null;
    }

    /**
     * get the name of the Id field
     */
    private Field findIdField() {
        final Field[] fields = clazz.getDeclaredFields();
        if (null != fields) {
            for (int i = 0; i < fields.length; i++) {
                final Field field = fields[i];
                final Id id = field.getAnnotation(Id.class);
                if (null != id) {
                    return field;
                }
            }
        }
        return null;
    }

    private Field[] findLazyLoadFields() throws CBeanException {
        final List<Field> fieldList = new ArrayList<Field>();
        for (int i = 0; i < persistableFields.length; i++) {
            final Field field = persistableFields[i];
            final Property property = field.getAnnotation(Property.class);
            /*
             * check if it's a lazy load
             */
            if (null != property) {
                if ((false == property.cascadeLoad()) && (true == CBean.isEntity(field.getType()))) {
                    fieldList.add(field);
                }
            }
        }
        final Field[] ret = new Field[fieldList.size()];
        fieldList.toArray(ret);
        return ret;
    }

    /**
     * find persistable fields
     */
    private Field[] findPersistableFields() {
        final List<Field> fieldList = new ArrayList<Field>();
        final Field[] fields = clazz.getDeclaredFields();
        if (null != fields) {
            for (int i = 0; i < fields.length; i++) {
                final Field field = fields[i];
                /*
                 * find annotations
                 */
                final Property property = field.getAnnotation(Property.class);
                final Id id = field.getAnnotation(Id.class);
                final Version version = field.getAnnotation(Version.class);
                /*
                 * persist?
                 */
                if ((null != id) || (null != version) || ((null != property) && (false == property.ignore()))) {
                    fieldList.add(field);
                }
            }
        }
        final Field[] ret = new Field[fieldList.size()];
        fieldList.toArray(ret);
        return ret;
    }

    /**
     * find version field
     */
    private Field findVersionField() {
        final Field[] fields = clazz.getDeclaredFields();
        if (null != fields) {
            for (int i = 0; i < fields.length; i++) {
                final Field field = fields[i];
                final Version version = field.getAnnotation(Version.class);
                if (null != version) {
                    return field;
                }
            }
        }
        return null;
    }

    public Class<?> getClazz() {
        return clazz;
    }

    /**
     * get the entity annotation
     */
    public Entity getEntity() {
        return clazz.getAnnotation(Entity.class);
    }

    public Id getId() {
        return id;
    }

    /**
     * get the Id field
     */
    public Field getIdField() {
        return idField;
    }

    public Field[] getLazyLoadFields() {
        return lazyLoadFields;
    }

    public Field[] getPersistableFields() {
        return persistableFields;
    }

    /**
     * get the property name from a getter method
     */
    public String getterToProperty(Method method) {
        return getterMap.get(method.getName());
    }

    public Field getVersionField() {
        return versionField;
    }

    /**
     * get the property name from a setter method
     */
    public String setterToProperty(Method method) {
        return setterMap.get(method.getName());
    }
}