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

com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty Maven / Gradle / Ivy

There is a newer version: 2.8.1
Show newest version
/**
 * Copyright (C) 2006  Robin Bygrave
 * 
 * This file is part of Ebean.
 * 
 * Ebean 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 2.1 of the License, or
 * (at your option) any later version.
 *  
 * Ebean 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 Ebean; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA  
 */
package com.avaje.ebeaninternal.server.deploy.meta;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.persistence.EmbeddedId;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.Version;

import com.avaje.ebean.annotation.CreatedTimestamp;
import com.avaje.ebean.annotation.UpdatedTimestamp;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebean.config.dbplatform.DbEncrypt;
import com.avaje.ebean.config.dbplatform.DbEncryptFunction;
import com.avaje.ebean.config.ldap.LdapAttributeAdapter;
import com.avaje.ebean.validation.factory.Validator;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter;
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.type.ScalarTypeEnum;
import com.avaje.ebeaninternal.server.type.ScalarTypeWrapper;

/**
 * Description of a property of a bean. Includes its deployment information such
 * as database column mapping information.
 */
public class DeployBeanProperty {

    private static final int ID_ORDER = 1000000;
    private static final int UNIDIRECTIONAL_ORDER = 100000;
    private static final int AUDITCOLUMN_ORDER = -1000000;
    private static final int VERSIONCOLUMN_ORDER = -1000000;

    /**
     * Advanced bean deployment. To exclude this property from update where
     * clause.
     */
    public static final String EXCLUDE_FROM_UPDATE_WHERE = "EXCLUDE_FROM_UPDATE_WHERE";

    /**
     * Advanced bean deployment. To exclude this property from delete where
     * clause.
     */
    public static final String EXCLUDE_FROM_DELETE_WHERE = "EXCLUDE_FROM_DELETE_WHERE";

    /**
     * Advanced bean deployment. To exclude this property from insert.
     */
    public static final String EXCLUDE_FROM_INSERT = "EXCLUDE_FROM_INSERT";

    /**
     * Advanced bean deployment. To exclude this property from update set
     * clause.
     */
    public static final String EXCLUDE_FROM_UPDATE = "EXCLUDE_FROM_UPDATE";

    /**
     * Flag to mark this at part of the unique id.
     */
    private boolean id;

    /**
     * Flag to mark the property as embedded. This could be on
     * BeanPropertyAssocOne rather than here. Put it here for checking Id type
     * (embedded or not).
     */
    private boolean embedded;

    /**
     * Flag indicating if this the version property.
     */
    private boolean versionColumn;

    private boolean fetchEager = true;

    /**
     * Set if this property is nullable.
     */
    private boolean nullable = true;

    private boolean unique;

    private LdapAttributeAdapter ldapAttributeAdapter;
    
    /**
     * The length or precision of the DB column.
     */
    private int dbLength;

    private int dbScale;

    private String dbColumnDefn;

    private boolean isTransient;

    private boolean localEncrypted;

    private boolean dbEncrypted;
    private DbEncryptFunction dbEncryptFunction;

    private int dbEncryptedType;

    private String dbBind = "?";

    /**
     * Is this property include in database resultSet.
     */
    private boolean dbRead;

    /**
     * Include this in DB insert.
     */
    private boolean dbInsertable;

    /**
     * Include this in a DB update.
     */
    private boolean dbUpdateable;

    private DeployTableJoin secondaryTableJoin;

    private String secondaryTableJoinPrefix;

    /**
     * Set to true if this property is based on a secondary table.
     */
    private String secondaryTable;

    /**
     * The type that owns this property.
     */
    private Class owningType;

    /**
     * True if the property is a Clob, Blob LongVarchar or LongVarbinary.
     */
    private boolean lob;

    /**
     * The logical bean property name.
     */
    private String name;

    /**
     * The reflected field.
     */
    private Field field;

    /**
     * The bean type.
     */
    private Class propertyType;

    /**
     * Set for Non-JDBC types to provide logical to db type conversion.
     */
    private ScalarType scalarType;

    /**
     * The database column. This can include quoted identifiers.
     */
    private String dbColumn;

    private String sqlFormulaSelect;
    private String sqlFormulaJoin;

    /**
     * The jdbc data type this maps to.
     */
    private int dbType;

    /**
     * The default value to insert if null.
     */
    private Object defaultValue;

    /**
     * Extra deployment parameters.
     */
    private HashMap extraAttributeMap = new HashMap();

    /**
     * The method used to read the property.
     */
    private Method readMethod;

    /**
     * The method used to write the property.
     */
    private Method writeMethod;

    private BeanReflectGetter getter;

    private BeanReflectSetter setter;

    /**
     * Generator for insert or update timestamp etc.
     */
    private GeneratedProperty generatedProperty;

    private List validators = new ArrayList();

    private final DeployBeanDescriptor desc;

    private boolean undirectionalShadow;
    
    private int sortOrder;

    public DeployBeanProperty(DeployBeanDescriptor desc, Class propertyType, ScalarType scalarType, ScalarTypeConverter typeConverter) {
        this.desc = desc;
        this.propertyType = propertyType;
        this.scalarType = wrapScalarType(propertyType, scalarType, typeConverter);
    }

    /**
     * Wrap the ScalarType using a ScalarTypeConverter.
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private ScalarType wrapScalarType(Class propertyType, ScalarType scalarType, ScalarTypeConverter typeConverter) {
        if (typeConverter == null){
            return scalarType;
        }
        return new ScalarTypeWrapper(propertyType, scalarType, typeConverter);
    }
    
    public int getSortOverride() {
        if (field == null) {
            return 0;
        }
        if (field.getAnnotation(Id.class) != null) {
            return ID_ORDER;
        } else if (field.getAnnotation(EmbeddedId.class) != null) {
            return ID_ORDER;
        } else if (undirectionalShadow){
            return UNIDIRECTIONAL_ORDER;
        } else if (field.getAnnotation(CreatedTimestamp.class) != null) {
            return AUDITCOLUMN_ORDER;
        } else if (field.getAnnotation(UpdatedTimestamp.class) != null) {
            return AUDITCOLUMN_ORDER;
        } else if (field.getAnnotation(Version.class) != null) {
            return VERSIONCOLUMN_ORDER;
        }
        return 0;
    }

    /**
     * Return true is this is a simple scalar property.
     */
    public boolean isScalar() {
        return true;
    }

    public String getFullBeanName() {
        return desc.getFullName() + "." + name;
    }

    /**
     * Return true if this is a primitive type with a nullable DB column.
     * 

* This should log a WARNING as primitive types can't be null. *

*/ public boolean isNullablePrimitive() { if (nullable && propertyType.isPrimitive()) { return true; } return false; } /** * Return the DB column length for character columns. *

* Note if there is no length explicitly defined then the scalarType is * checked to see if that has one (primarily to support putting a length on * Enum types). *

*/ public int getDbLength() { if (dbLength == 0 && scalarType != null) { return scalarType.getLength(); } return dbLength; } /** * Return the sortOrder for the properties. */ public int getSortOrder() { return sortOrder; } /** * Set the sortOrder for the properties. */ public void setSortOrder(int sortOrder) { this.sortOrder = sortOrder; } /** * Return true if this is a placeholder property for a unidirectional relationship. */ public boolean isUndirectionalShadow() { return undirectionalShadow; } /** * Mark this property as a placeholder for a unidirectional relationship. */ public void setUndirectionalShadow(boolean undirectionalShadow) { this.undirectionalShadow = undirectionalShadow; } /** * Return true if the property is encrypted in java rather than in the DB. */ public boolean isLocalEncrypted() { return localEncrypted; } /** * Set to true when the property is encrypted in java rather than in the DB. */ public void setLocalEncrypted(boolean localEncrypted) { this.localEncrypted = localEncrypted; } /** * Set the DB column length for character columns. */ public void setDbLength(int dbLength) { this.dbLength = dbLength; } /** * Return the Db scale for numeric columns. */ public int getDbScale() { return dbScale; } /** * Set the Db scale for numeric columns. */ public void setDbScale(int dbScale) { this.dbScale = dbScale; } /** * Return the DB column definition if defined. */ public String getDbColumnDefn() { return dbColumnDefn; } /** * Set a specific DB column definition. */ public void setDbColumnDefn(String dbColumnDefn) { if (dbColumnDefn == null || dbColumnDefn.trim().length() == 0) { this.dbColumnDefn = null; } else { this.dbColumnDefn = InternString.intern(dbColumnDefn); } } public String getDbConstraintExpression() { if (scalarType instanceof ScalarTypeEnum) { // create a check constraint for the enum ScalarTypeEnum etype = (ScalarTypeEnum) scalarType; // check dbColName IN ('A', 'I', 'D') return "check (" + dbColumn + " in " + etype.getContraintInValues() + ")"; } return null; } /** * Add a validator to this property. */ public void addValidator(Validator validator) { validators.add(validator); } /** * Return true if the property contains a validator of a given type. *

* Used to detect if a validator has already been assigned when trying to * automatically add validators such as Length and NotNull. *

*/ public boolean containsValidatorType(Class type) { Iterator it = validators.iterator(); while (it.hasNext()) { Validator validator = (Validator) it.next(); if (validator.getClass().equals(type)) { return true; } } return false; } /** * Return the validators for this property. */ public Validator[] getValidators() { return validators.toArray(new Validator[validators.size()]); } /** * Return the scalarType. This returns null for native JDBC types, otherwise * it is used to convert between logical types and jdbc types. */ public ScalarType getScalarType() { return scalarType; } public void setScalarType(ScalarType scalarType) { this.scalarType = scalarType; } public BeanReflectGetter getGetter() { return getter; } public BeanReflectSetter getSetter() { return setter; } /** * Return the getter method. */ public Method getReadMethod() { return readMethod; } /** * Return the setter method. */ public Method getWriteMethod() { return writeMethod; } /** * Set to the owning type form a Inheritance heirarchy. */ public void setOwningType(Class owningType) { this.owningType = owningType; } public Class getOwningType() { return owningType; } /** * Return true if this is local to this type - aka not from a super type. */ public boolean isLocal() { return owningType == null || owningType.equals(desc.getBeanType()); } /** * Set the getter used to read the property value from a bean. */ public void setGetter(BeanReflectGetter getter) { this.getter = getter; } /** * Set the setter used to set the property value to a bean. */ public void setSetter(BeanReflectSetter setter) { this.setter = setter; } /** * Return the name of the property. */ public String getName() { return name; } /** * Set the name of the property. */ public void setName(String name) { this.name = InternString.intern(name); } /** * Return the bean Field associated with this property. */ public Field getField() { return field; } /** * Set the bean Field associated with this property. */ public void setField(Field field) { this.field = field; } /** * Return true if this is a generated property like update timestamp and * create timestamp. */ public boolean isGenerated() { return generatedProperty != null; } /** * Return the GeneratedValue. Used to generate update timestamp etc. */ public GeneratedProperty getGeneratedProperty() { return generatedProperty; } /** * Set the GeneratedValue. Used to generate update timestamp etc. */ public void setGeneratedProperty(GeneratedProperty generatedValue) { this.generatedProperty = generatedValue; } /** * Return true if this property is mandatory. */ public boolean isNullable() { return nullable; } /** * Set the not nullable of this property. */ public void setNullable(boolean isNullable) { this.nullable = isNullable; } /** * Return true if the DB column is unique. */ public boolean isUnique() { return unique; } /** * Set to true if the DB column is unique. */ public void setUnique(boolean unique) { this.unique = unique; } /** * Return the LdapAttributeAdapter. */ public LdapAttributeAdapter getLdapAttributeAdapter() { return ldapAttributeAdapter; } /** * Set the LdapAttributeAdapter. */ public void setLdapAttributeAdapter(LdapAttributeAdapter ldapAttributeAdapter) { this.ldapAttributeAdapter = ldapAttributeAdapter; } /** * Return true if this is a version column used for concurrency checking. */ public boolean isVersionColumn() { return versionColumn; } /** * Set if this is a version column used for concurrency checking. */ public void setVersionColumn(boolean isVersionColumn) { this.versionColumn = isVersionColumn; } /** * Return true if this should be eager fetched by default. */ public boolean isFetchEager() { return fetchEager; } /** * Set the default fetch type for this property. */ public void setFetchType(FetchType fetchType) { this.fetchEager = FetchType.EAGER.equals(fetchType); } /** * Return the formula this property is based on. */ public String getSqlFormulaSelect() { return sqlFormulaSelect; } public String getSqlFormulaJoin() { return sqlFormulaJoin; } /** * The property is based on a formula. */ public void setSqlFormula(String formulaSelect, String formulaJoin) { this.sqlFormulaSelect = formulaSelect; this.sqlFormulaJoin = formulaJoin.equals("") ? null : formulaJoin; this.dbRead = true; this.dbInsertable = false; this.dbUpdateable = false; } public String getElPlaceHolder(EntityType et) { if (sqlFormulaSelect != null) { return sqlFormulaSelect; } else if (EntityType.LDAP.equals(et)){ return dbColumn; } else { if (secondaryTableJoinPrefix != null){ return "${"+secondaryTableJoinPrefix+"}"+dbColumn; } // prepend table alias placeholder return ElPropertyValue.ROOT_ELPREFIX + dbColumn; } } /** * The database column name this is mapped to. */ public String getDbColumn() { if (sqlFormulaSelect != null) { return sqlFormulaSelect; } return dbColumn; } /** * Set the database column name this is mapped to. */ public void setDbColumn(String dbColumn) { this.dbColumn = InternString.intern(dbColumn); } /** * Return the database jdbc data type this is mapped to. */ public int getDbType() { return dbType; } /** * Set the database jdbc data type this is mapped to. */ public void setDbType(int dbType) { this.dbType = dbType; this.lob = isLobType(dbType); } /** * Return true if this is mapped to a Clob Blob LongVarchar or * LongVarbinary. */ public boolean isLob() { return lob; } private boolean isLobType(int type) { switch (type) { case Types.CLOB: return true; case Types.BLOB: return true; case Types.LONGVARBINARY: return true; case Types.LONGVARCHAR: return true; default: return false; } } /** * Return true if this property is based on a secondary table. */ public boolean isSecondaryTable() { return secondaryTable != null; } /** * Return the secondary table this property is associated with. */ public String getSecondaryTable() { return secondaryTable; } /** * Set to true if this property is included in persisting. */ public void setSecondaryTable(String secondaryTable) { this.secondaryTable = secondaryTable; this.dbInsertable = false; this.dbUpdateable = false; } /** * */ public String getSecondaryTableJoinPrefix() { return secondaryTableJoinPrefix; } public DeployTableJoin getSecondaryTableJoin() { return secondaryTableJoin; } public void setSecondaryTableJoin(DeployTableJoin secondaryTableJoin, String prefix) { this.secondaryTableJoin = secondaryTableJoin; this.secondaryTableJoinPrefix = prefix; } /** * Return the DB Bind parameter. Typically is "?" but can be different for * encrypted bind. */ public String getDbBind() { return dbBind; } /** * Set the DB bind parameter (if different from "?"). */ public void setDbBind(String dbBind) { this.dbBind = dbBind; } /** * Return true if this property is encrypted in the DB. */ public boolean isDbEncrypted() { return dbEncrypted; } // /** // * Set true if this property should be encrypted in the DB. // */ // public void setDbEncrypted(boolean dbEncrypted) { // this.dbEncrypted = dbEncrypted; // } public DbEncryptFunction getDbEncryptFunction() { return dbEncryptFunction; } public void setDbEncryptFunction(DbEncryptFunction dbEncryptFunction, DbEncrypt dbEncrypt, int dbLen) { this.dbEncryptFunction = dbEncryptFunction; this.dbEncrypted = true; this.dbBind = dbEncryptFunction.getEncryptBindSql(); this.dbEncryptedType = isLob() ? Types.BLOB : dbEncrypt.getEncryptDbType(); if (dbLen > 0){ setDbLength(dbLen); } } /** * Return the DB type for the encrypted property. This can differ from the * logical type (String encrypted and stored in a VARBINARY) */ public int getDbEncryptedType() { return dbEncryptedType; } /** * Set the DB type used to store the encrypted value. */ public void setDbEncryptedType(int dbEncryptedType) { this.dbEncryptedType = dbEncryptedType; } /** * Return true if this property is included in database queries. */ public boolean isDbRead() { return dbRead; } /** * Set to true if this property is included in database queries. */ public void setDbRead(boolean isDBRead) { this.dbRead = isDBRead; } public boolean isDbInsertable() { return dbInsertable; } public void setDbInsertable(boolean insertable) { this.dbInsertable = insertable; } public boolean isDbUpdateable() { return dbUpdateable; } public void setDbUpdateable(boolean updateable) { this.dbUpdateable = updateable; } /** * Return true if the property is transient. */ public boolean isTransient() { return isTransient; } /** * Mark the property explicitly as a transient property. */ public void setTransient(boolean isTransient) { this.isTransient = isTransient; } /** * Set the bean read method. *

* NB: That a BeanReflectGetter is used to actually perform the getting of * property values from a bean. This is due to performance considerations. *

*/ public void setReadMethod(Method readMethod) { this.readMethod = readMethod; } /** * Set the bean write method. *

* NB: That a BeanReflectSetter is used to actually perform the setting of * property values to a bean. This is due to performance considerations. *

*/ public void setWriteMethod(Method writeMethod) { this.writeMethod = writeMethod; } /** * Return the property type. */ public Class getPropertyType() { return propertyType; } /** * Return true if this is included in the unique id. */ public boolean isId() { return id; } /** * Set to true if this is included in the unique id. */ public void setId(boolean id) { this.id = id; } /** * Return true if this is an Embedded property. In this case it shares the * table and pk of its owner object. */ public boolean isEmbedded() { return embedded; } /** * Set to true if this is an embedded property. */ public void setEmbedded(boolean embedded) { this.embedded = embedded; } public Map getExtraAttributeMap() { return extraAttributeMap; } /** * Return an extra attribute set on this property. */ public String getExtraAttribute(String key) { return (String) extraAttributeMap.get(key); } /** * Set an extra attribute set on this property. */ public void setExtraAttribute(String key, String value) { extraAttributeMap.put(key, value); } /** * Return the default value. */ public Object getDefaultValue() { return defaultValue; } /** * Set the default value. Inserted if the value is null. */ public void setDefaultValue(Object defaultValue) { this.defaultValue = defaultValue; } public String toString() { return desc.getFullName() + "." + name; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy