package com.avaje.ebeaninternal.server.deploy; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.sql.SQLException; import java.sql.Types; import java.util.List; import java.util.Map; import javax.persistence.PersistenceException; import com.avaje.ebean.bean.EntityBean; import com.avaje.ebean.config.EncryptKey; import com.avaje.ebean.config.dbplatform.DbEncryptFunction; import com.avaje.ebean.config.dbplatform.DbType; import com.avaje.ebean.text.StringFormatter; import com.avaje.ebean.text.StringParser; import com.avaje.ebean.text.TextException; 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.deploy.meta.DeployBeanProperty; import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder; import com.avaje.ebeaninternal.server.el.ElPropertyValue; import com.avaje.ebeaninternal.server.lib.util.StringHelper; import com.avaje.ebeaninternal.server.query.SqlBeanLoad; import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter; import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter; import com.avaje.ebeaninternal.server.text.json.ReadJsonContext; import com.avaje.ebeaninternal.server.text.json.WriteJsonContext; import com.avaje.ebeaninternal.server.type.DataBind; import com.avaje.ebeaninternal.server.type.ScalarType; import com.avaje.ebeaninternal.util.ValueUtil; /** * Description of a property of a bean. Includes its deployment information such * as database column mapping information. */ public class BeanProperty implements ElPropertyValue { /** * 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. */ final boolean id; /** * Flag to make this as a dummy property for unidirecitonal relationships. */ final boolean unidirectionalShadow; /** * 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). */ final boolean embedded; /** * Flag indicating if this the version property. */ final boolean version; final boolean naturalKey; /** * Set if this property is nullable. */ final boolean nullable; final boolean unique; /** * Is this property include in database resultSet. */ final boolean dbRead; /** * Include in DB insert. */ final boolean dbInsertable; /** * Include in DB update. */ final boolean dbUpdatable; /** * True if the property is based on a SECONDARY table. */ final boolean secondaryTable; final TableJoin secondaryTableJoin; final String secondaryTableJoinPrefix; /** * The property is inherited from a super class. */ final boolean inherited; final Class owningType; final boolean local; /** * True if the property is a Clob, Blob LongVarchar or LongVarbinary. */ final boolean lob; final boolean fetchEager; final boolean isTransient; /** * The logical bean property name. */ final String name; /** * The reflected field. */ final Field field; /** * The bean type. */ final Class propertyType; final String dbBind; /** * The database column. This can include quoted identifiers. */ final String dbColumn; final String elPlaceHolder; final String elPlaceHolderEncrypted; /** * Select part of a SQL Formula used to populate this property. */ final String sqlFormulaSelect; /** * Join part of a SQL Formula. */ final String sqlFormulaJoin; final boolean formula; /** * Set to true if stored encrypted. */ final boolean dbEncrypted; final boolean localEncrypted; final int dbEncryptedType; /** * The jdbc data type this maps to. */ final int dbType; /** * The default value to insert if null. */ final Object defaultValue; /** * Extra deployment parameters. */ final Map extraAttributeMap; /** * The method used to read the property. */ final Method readMethod; /** * The method used to write the property. */ final Method writeMethod; /** * Generator for insert or update timestamp etc. */ final GeneratedProperty generatedProperty; final BeanReflectGetter getter; final BeanReflectSetter setter; final BeanDescriptor descriptor; /** * Used for non-jdbc native types (java.util.Date Enums etc). Converts from * logical to jdbc types. */ @SuppressWarnings("rawtypes") final ScalarType scalarType; boolean cascadeValidate; /** * The length or precision for DB column. */ final int dbLength; /** * The scale for DB column (decimal). */ final int dbScale; /** * Deployment defined DB column definition. */ final String dbColumnDefn; /** * DB Constraint (typically check constraint on enum) */ final String dbConstraintExpression; final DbEncryptFunction dbEncryptFunction; final boolean dynamicSubclassWithInheritance; int deployOrder; final boolean jsonSerialize; final boolean jsonDeserialize; public BeanProperty(DeployBeanProperty deploy) { this(null, null, deploy); } public BeanProperty(BeanDescriptorMap owner, BeanDescriptor descriptor, DeployBeanProperty deploy) { this.descriptor = descriptor; this.name = InternString.intern(deploy.getName()); if (descriptor != null) { this.dynamicSubclassWithInheritance = (descriptor.isDynamicSubclass() && descriptor.hasInheritance()); } else { this.dynamicSubclassWithInheritance = false; } this.unidirectionalShadow = deploy.isUndirectionalShadow(); this.localEncrypted = deploy.isLocalEncrypted(); this.dbEncrypted = deploy.isDbEncrypted(); this.dbEncryptedType = deploy.getDbEncryptedType(); this.dbEncryptFunction = deploy.getDbEncryptFunction(); this.dbBind = deploy.getDbBind(); this.dbRead = deploy.isDbRead(); this.dbInsertable = deploy.isDbInsertable(); this.dbUpdatable = deploy.isDbUpdateable(); this.secondaryTable = deploy.isSecondaryTable(); if (secondaryTable) { this.secondaryTableJoin = new TableJoin(deploy.getSecondaryTableJoin(), null); this.secondaryTableJoinPrefix = deploy.getSecondaryTableJoinPrefix(); } else { this.secondaryTableJoin = null; this.secondaryTableJoinPrefix = null; } this.fetchEager = deploy.isFetchEager(); this.isTransient = deploy.isTransient(); this.nullable = deploy.isNullable(); this.unique = deploy.isUnique(); this.naturalKey = deploy.isNaturalKey(); this.dbLength = deploy.getDbLength(); this.dbScale = deploy.getDbScale(); this.dbColumnDefn = InternString.intern(deploy.getDbColumnDefn()); this.dbConstraintExpression = InternString.intern(deploy.getDbConstraintExpression()); this.inherited = false;// deploy.isInherited(); this.owningType = deploy.getOwningType(); this.local = deploy.isLocal(); this.version = deploy.isVersionColumn(); this.embedded = deploy.isEmbedded(); this.id = deploy.isId(); this.generatedProperty = deploy.getGeneratedProperty(); this.readMethod = deploy.getReadMethod(); this.writeMethod = deploy.getWriteMethod(); this.getter = deploy.getGetter(); if (descriptor != null && getter == null) { if (!unidirectionalShadow) { String m = "Null Getter for: " + getFullBeanName(); throw new RuntimeException(m); } } this.setter = deploy.getSetter(); this.dbColumn = tableAliasIntern(descriptor, deploy.getDbColumn(), false, null); this.sqlFormulaJoin = InternString.intern(deploy.getSqlFormulaJoin()); this.sqlFormulaSelect = InternString.intern(deploy.getSqlFormulaSelect()); this.formula = sqlFormulaSelect != null; this.extraAttributeMap = deploy.getExtraAttributeMap(); this.defaultValue = deploy.getDefaultValue(); this.dbType = deploy.getDbType(); this.scalarType = deploy.getScalarType(); this.lob = isLobType(dbType); this.propertyType = deploy.getPropertyType(); this.field = deploy.getField(); EntityType et = descriptor == null ? null : descriptor.getEntityType(); this.elPlaceHolder = tableAliasIntern(descriptor, deploy.getElPlaceHolder(et), false, null); this.elPlaceHolderEncrypted = tableAliasIntern(descriptor, deploy.getElPlaceHolder(et), dbEncrypted, dbColumn); this.jsonSerialize = deploy.isExposeSerialize(); this.jsonDeserialize = deploy.isExposeDeserialize(); } private String tableAliasIntern(BeanDescriptor descriptor, String s, boolean dbEncrypted, String dbColumn) { if (descriptor != null) { s = StringHelper.replaceString(s, "${ta}.", "${}"); s = StringHelper.replaceString(s, "${ta}", "${}"); if (dbEncrypted) { s = dbEncryptFunction.getDecryptSql(s); String namedParam = ":encryptkey_" + descriptor.getBaseTable() + "___" + dbColumn; s = StringHelper.replaceString(s, "?", namedParam); } } return InternString.intern(s); } /** * Create a Matching BeanProperty with some attributes overridden. *

* Primarily for supporting Embedded beans with overridden dbColumn * mappings. *

*/ public BeanProperty(BeanProperty source, BeanPropertyOverride override) { this.descriptor = source.descriptor; this.name = InternString.intern(source.getName()); this.dynamicSubclassWithInheritance = source.dynamicSubclassWithInheritance; this.dbColumn = InternString.intern(override.getDbColumn()); this.sqlFormulaJoin = InternString.intern(override.getSqlFormulaJoin()); this.sqlFormulaSelect = InternString.intern(override.getSqlFormulaSelect()); this.formula = sqlFormulaSelect != null; this.fetchEager = source.fetchEager; this.unidirectionalShadow = source.unidirectionalShadow; this.localEncrypted = source.isLocalEncrypted(); this.isTransient = source.isTransient(); this.secondaryTable = source.isSecondaryTable(); this.secondaryTableJoin = source.secondaryTableJoin; this.secondaryTableJoinPrefix = source.secondaryTableJoinPrefix; this.dbBind = source.getDbBind(); this.dbEncrypted = source.isDbEncrypted(); this.dbEncryptedType = source.getDbEncryptedType(); this.dbEncryptFunction = source.dbEncryptFunction; this.dbRead = source.isDbRead(); this.dbInsertable = source.isDbInsertable(); this.dbUpdatable = source.isDbUpdatable(); this.nullable = source.isNullable(); this.unique = source.isUnique(); this.naturalKey = source.isNaturalKey(); this.dbLength = source.getDbLength(); this.dbScale = source.getDbScale(); this.dbColumnDefn = InternString.intern(source.getDbColumnDefn()); this.dbConstraintExpression = InternString.intern(source.getDbConstraintExpression()); this.inherited = source.isInherited(); this.owningType = source.owningType; this.local = owningType.equals(descriptor.getBeanType()); this.version = source.isVersion(); this.embedded = source.isEmbedded(); this.id = source.isId(); this.generatedProperty = source.getGeneratedProperty(); this.readMethod = source.getReadMethod(); this.writeMethod = source.getWriteMethod(); this.getter = source.getter; this.setter = source.setter; this.extraAttributeMap = source.extraAttributeMap; this.defaultValue = source.getDefaultValue(); this.dbType = source.getDbType(); this.scalarType = source.scalarType; this.lob = isLobType(dbType); this.propertyType = source.getPropertyType(); this.field = source.getField(); this.elPlaceHolder = override.replace(source.elPlaceHolder, source.dbColumn); this.elPlaceHolderEncrypted = override.replace(source.elPlaceHolderEncrypted, source.dbColumn); this.jsonSerialize = source.jsonSerialize; this.jsonDeserialize = source.jsonDeserialize; } /** * Initialise the property before returning to client code. Used to * initialise variables that can't be done in construction due to recursive * issues. */ public void initialise() { // do nothing for normal BeanProperty if (!isTransient && scalarType == null) { String msg = "No ScalarType assigned to " + descriptor.getFullName() + "." + getName(); throw new RuntimeException(msg); } } /** * Return the order this property appears in the bean. */ public int getDeployOrder() { return deployOrder; } /** * Set the order this property appears in the bean. */ public void setDeployOrder(int deployOrder) { this.deployOrder = deployOrder; } public ElPropertyValue buildElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) { throw new PersistenceException("Not valid on scalar bean property " + getFullBeanName()); } /** * Return the BeanDescriptor that owns this property. */ public BeanDescriptor getBeanDescriptor() { return descriptor; } /** * Return true is this is a simple scalar property. */ public boolean isScalar() { return true; } /** * Return true if this property is based on a formula. */ public boolean isFormula() { return formula; } public boolean hasChanged(Object bean, Object oldValues) { Object value = getValue(bean); Object oldVal = getValue(oldValues); return !ValueUtil.areEqual(value, oldVal); } public void copyProperty(Object sourceBean, Object destBean) { Object value = getValue(sourceBean); setValue(destBean, value); } /** * Return the encrypt key for the column matching this property. */ public EncryptKey getEncryptKey() { return descriptor.getEncryptKey(this); } public String getDecryptProperty() { return dbEncryptFunction.getDecryptSql(this.getName()); } public String getDecryptProperty(String propertyName) { return dbEncryptFunction.getDecryptSql(propertyName); } public String getDecryptSql() { return dbEncryptFunction.getDecryptSql(this.getDbColumn()); } public String getDecryptSql(String tableAlias) { return dbEncryptFunction.getDecryptSql(tableAlias + "." + this.getDbColumn()); } /** * Add any extra joins required to support this property. Generally a no * operation except for a OneToOne exported. */ public void appendFrom(DbSqlContext ctx, boolean forceOuterJoin) { if (formula && sqlFormulaJoin != null) { ctx.appendFormulaJoin(sqlFormulaJoin, forceOuterJoin); } else if (secondaryTableJoin != null) { String relativePrefix = ctx.getRelativePrefix(secondaryTableJoinPrefix); secondaryTableJoin.addJoin(forceOuterJoin, relativePrefix, ctx); } } /** * Returns null unless this property is using a secondary table. In that * case this returns the logical property prefix. */ public String getSecondaryTableJoinPrefix() { return secondaryTableJoinPrefix; } public void appendSelect(DbSqlContext ctx, boolean subQuery) { if (formula) { ctx.appendFormulaSelect(sqlFormulaSelect); } else if (!isTransient) { if (secondaryTableJoin != null) { String relativePrefix = ctx.getRelativePrefix(secondaryTableJoinPrefix); ctx.pushTableAlias(relativePrefix); } if (dbEncrypted) { String decryptSql = getDecryptSql(ctx.peekTableAlias()); ctx.appendRawColumn(decryptSql); ctx.addEncryptedProp(this); } else { ctx.appendColumn(dbColumn); } if (secondaryTableJoin != null) { ctx.popTableAlias(); } } } public boolean isAssignableFrom(Class type) { return owningType.isAssignableFrom(type); } public Object readSetOwning(DbReadContext ctx, Object bean, Class type) throws SQLException { try { Object value = scalarType.read(ctx.getDataReader()); if (value == null || bean == null) { // not setting the value... } else { if (owningType.equals(type)) { setValue(bean, value); } } return value; } catch (Exception e) { String msg = "Error readSet on " + descriptor + "." + name; throw new PersistenceException(msg, e); } } public void loadIgnore(DbReadContext ctx) { scalarType.loadIgnore(ctx.getDataReader()); } public void load(SqlBeanLoad sqlBeanLoad) throws SQLException { sqlBeanLoad.load(this); } public void buildSelectExpressionChain(String prefix, List selectChain) { if (prefix == null) { selectChain.add(name); } else { selectChain.add(prefix + "." + name); } } public Object read(DbReadContext ctx) throws SQLException { return scalarType.read(ctx.getDataReader()); } public Object readSet(DbReadContext ctx, Object bean, Class type) throws SQLException { try { Object value = scalarType.read(ctx.getDataReader()); if (bean == null || (type != null && !owningType.isAssignableFrom(type))) { // not setting the value... } else { setValue(bean, value); } return value; } catch (Exception e) { String msg = "Error readSet on " + descriptor + "." + name; throw new PersistenceException(msg, e); } } /** * Convert the type to the bean type if required. *

* Generally only used to ensure id properties are converted for * Query.setId() use. *

*/ public Object toBeanType(Object value) { return scalarType.toBeanType(value); } @SuppressWarnings("unchecked") public void bind(DataBind b, Object value) throws SQLException { scalarType.bind(b, value); } public void writeData(DataOutput dataOutput, Object value) throws IOException { scalarType.writeData(dataOutput, value); } public Object readData(DataInput dataInput) throws IOException { return scalarType.readData(dataInput); } public boolean isCascadeValidate() { return cascadeValidate; } /** * Checks to see if a bean is a reference (will be lazy loaded) or a * BeanCollection that has not yet been populated. *

* For base types this returns true. *

*/ public boolean isValueLoaded(Object value) { return true; } public BeanProperty getBeanProperty() { return this; } /** * Return the getter method. */ public Method getReadMethod() { return readMethod; } /** * Return the setter method. */ public Method getWriteMethod() { return writeMethod; } /** * Return true if this object is part of an inheritance hierarchy. */ public boolean isInherited() { return inherited; } /** * Return true is this type is not from a super type. */ public boolean isLocal() { return local; } /** * Set the value of the property without interception or * PropertyChangeSupport. */ public void setValue(Object bean, Object value) { try { if (bean instanceof EntityBean) { setter.set(bean, value); } else { Object[] args = new Object[1]; args[0] = value; writeMethod.invoke(bean, args); } } catch (Exception ex) { String beanType = bean == null ? "null" : bean.getClass().getName(); String msg = "set " + name + " on [" + descriptor + "] arg[" + value + "] type[" + beanType + "] threw error"; throw new RuntimeException(msg, ex); } } /** * Set the value of the property. */ public void setValueIntercept(Object bean, Object value) { try { if (bean instanceof EntityBean) { setter.setIntercept(bean, value); } else { Object[] args = new Object[1]; args[0] = value; writeMethod.invoke(bean, args); } } catch (Exception ex) { String beanType = bean == null ? "null" : bean.getClass().getName(); String msg = "setIntercept " + name + " on [" + descriptor + "] arg[" + value + "] type[" + beanType + "] threw error"; throw new RuntimeException(msg, ex); } } private static Object[] NO_ARGS = new Object[0]; /** * Return the property value taking inheritance into account. */ public Object getValueWithInheritance(Object bean) { if (dynamicSubclassWithInheritance) { return descriptor.getBeanPropertyWithInheritance(bean, name); } return getValue(bean); } public Object getCacheDataValue(Object bean){ return getValue(bean); } public void setCacheDataValue(Object bean, Object cacheData, Object oldValues, boolean readOnly){ setValue(bean, cacheData); } /** * Return the value of the property method. */ public Object getValue(Object bean) { try { if (bean instanceof EntityBean) { return getter.get(bean); } else { return readMethod.invoke(bean, NO_ARGS); } } catch (Exception ex) { String beanType = bean == null ? "null" : bean.getClass().getName(); String msg = "get " + name + " on [" + descriptor + "] type[" + beanType + "] threw error."; throw new RuntimeException(msg, ex); } } /** * Explicitly use reflection to get value. */ public Object getValueViaReflection(Object bean) { try { return readMethod.invoke(bean, NO_ARGS); } catch (Exception ex) { String beanType = bean == null ? "null" : bean.getClass().getName(); String msg = "get " + name + " on [" + descriptor + "] type[" + beanType + "] threw error."; throw new RuntimeException(msg, ex); } } public Object getValueIntercept(Object bean) { try { if (bean instanceof EntityBean) { return getter.getIntercept(bean); } else { return readMethod.invoke(bean, NO_ARGS); } } catch (Exception ex) { String beanType = bean == null ? "null" : bean.getClass().getName(); String msg = "getIntercept " + name + " on [" + descriptor + "] type[" + beanType + "] threw error."; throw new RuntimeException(msg, ex); } } public Object elConvertType(Object value) { if (value == null) { return null; } return convertToLogicalType(value); } public void elSetReference(Object bean) { throw new RuntimeException("Should not be called"); } public void elSetValue(Object bean, Object value, boolean populate, boolean reference) { if (bean != null) { setValueIntercept(bean, value); } } public Object elGetValue(Object bean) { if (bean == null) { return null; } return getValueIntercept(bean); } public Object elGetReference(Object bean) { throw new RuntimeException("Not expected to call this"); } /** * Return the name of the property. */ public String getName() { return name; } public String getElName() { return name; } /** * This is a full ElGetValue. */ public boolean isDeployOnly() { return false; } @Override public boolean containsFormulaWithJoin() { return formula && sqlFormulaJoin != null; } public boolean containsManySince(String sinceProperty) { return containsMany(); } public boolean containsMany() { return false; } public Object[] getAssocOneIdValues(Object bean) { // Returns null as not an AssocOne. return null; } public String getAssocOneIdExpr(String prefix, String operator) { // Returns null as not an AssocOne. return null; } public String getAssocIdInExpr(String prefix) { // Returns null as not an AssocOne. return null; } public String getAssocIdInValueExpr(int size) { // Returns null as not an AssocOne. return null; } public boolean isAssocId() { // Returns false - override in BeanPropertyAssocOne. return false; } public boolean isAssocProperty() { // Returns false - override in BeanPropertyAssocOne. return false; } public String getElPlaceholder(boolean encrypted) { return encrypted ? elPlaceHolderEncrypted : elPlaceHolder; } public String getElPrefix() { return secondaryTableJoinPrefix; } /** * Return the full name of this property. */ public String getFullBeanName() { return descriptor.getFullName() + "." + name; } /** * Return the scalarType. */ public ScalarType getScalarType() { return scalarType; } public StringFormatter getStringFormatter() { return scalarType; } public StringParser getStringParser() { return scalarType; } public boolean isDateTimeCapable() { return scalarType != null && scalarType.isDateTimeCapable(); } public int getJdbcType() { return scalarType == null ? 0 : scalarType.getJdbcType(); } public Object parseDateTime(long systemTimeMillis) { return scalarType.parseDateTime(systemTimeMillis); } /** * Return the DB max length (varchar) or precision (decimal). */ public int getDbLength() { return dbLength; } /** * Return the DB scale for numeric columns. */ public int getDbScale() { return dbScale; } /** * Return a specific column DDL definition if specified (otherwise null). */ public String getDbColumnDefn() { return dbColumnDefn; } /** * Return the DB constraint expression (can be null). *

* For an Enum returns IN expression for the set of Enum values. *

*/ public String getDbConstraintExpression() { return dbConstraintExpression; } /** * Return the DB column type definition. */ public String renderDbType(DbType dbType) { if (dbColumnDefn != null) { return dbColumnDefn; } return dbType.renderType(dbLength, dbScale); } /** * Return the bean Field associated with this property. */ public Field getField() { return field; } /** * Return the GeneratedValue. Used to generate update timestamp etc. */ public GeneratedProperty getGeneratedProperty() { return generatedProperty; } /** * Return true if this is the natural key property. */ public boolean isNaturalKey() { return naturalKey; } /** * Return true if this property is mandatory. */ public boolean isNullable() { return nullable; } /** * Return true if DDL Not NULL constraint should be defined for this column * based on it being a version column or having a generated property. */ public boolean isDDLNotNull() { return isVersion() || (generatedProperty != null && generatedProperty.isDDLNotNullable()); } /** * Return true if the DB column should be unique. */ public boolean isUnique() { return unique; } /** * Return true if the property is transient. */ public boolean isTransient() { return isTransient; } /** * Return true if this is a version column used for concurrency checking. */ public boolean isVersion() { return version; } public String getDeployProperty() { return dbColumn; } /** * The database column name this is mapped to. */ public String getDbColumn() { return dbColumn; } /** * Return the database jdbc data type this is mapped to. */ public int getDbType() { return dbType; } /** * Perform DB to Logical type conversion (if necessary). */ public Object convertToLogicalType(Object value) { if (scalarType != null) { return scalarType.toBeanType(value); } return value; } // private ArrayList luceneIndexes; // // public void registerLuceneIndex(LuceneIndex luceneIndex) { // if (luceneIndexes == null) { // luceneIndexes = new ArrayList(); // } // luceneIndexes.add(luceneIndex); // } // // public boolean isDeltaRequired() { // return true;//luceneIndexes != null; // } /** * Return true if by default this property is set to fetch eager. * Lob's usually default to fetch lazy. */ public boolean isFetchEager() { return fetchEager; } /** * 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 the DB bind parameter. Typically is "?" but different for * encrypted bind. */ public String getDbBind() { return dbBind; } /** * Returns true if DB encrypted. */ public boolean isLocalEncrypted() { return localEncrypted; } /** * Return true if this property is stored encrypted. */ public boolean isDbEncrypted() { return dbEncrypted; } public int getDbEncryptedType() { return dbEncryptedType; } /** * Return true if this property should be included in an Insert. */ public boolean isDbInsertable() { return dbInsertable; } /** * Return true if this property should be included in an Update. */ public boolean isDbUpdatable() { return dbUpdatable; } /** * Return true if this property is included in database queries. */ public boolean isDbRead() { return dbRead; } /** * Return true if this property is based on a secondary table (not the base * table). */ public boolean isSecondaryTable() { return secondaryTable; } /** * Return the property type. */ public Class getPropertyType() { return propertyType; } /** * Return true if this is included in the unique id. */ public boolean isId() { return id; } /** * Return true if this is an Embedded property. In this case it shares the * table and primary key of its owner object. */ public boolean isEmbedded() { return embedded; } /** * Return an extra attribute set on this property. */ public String getExtraAttribute(String key) { return extraAttributeMap.get(key); } /** * Return the default value. */ public Object getDefaultValue() { return defaultValue; } public String toString() { return name; } @SuppressWarnings("unchecked") public void jsonWrite(WriteJsonContext ctx, Object bean) { if(!jsonSerialize){ return; } Object value = getValueIntercept(bean); if (value == null) { ctx.appendNull(name); } else { ctx.appendNameValue(name, scalarType, value); } } public void jsonRead(ReadJsonContext ctx, Object bean) { if(!jsonDeserialize){ return; } String jsonValue; try { jsonValue = ctx.readScalarValue(); } catch (TextException e){ throw new TextException("Error reading property "+getFullBeanName(), e); } Object objValue; if (jsonValue == null) { objValue = null; } else { objValue = scalarType.jsonFromString(jsonValue, ctx.getValueAdapter()); } setValue(bean, objValue); } }