From 07cdb69a5b5299413e367c0d1dc2cfe3548da894 Mon Sep 17 00:00:00 2001 From: rbygrave Date: Tue, 18 Nov 2014 23:09:26 +1300 Subject: [PATCH] Add Period support via CompoundTypePeriod, rename server/reflect to server/properties --- .../server/deploy/BeanDescriptorManager.java | 18 +- .../server/deploy/BeanProperty.java | 17 +- .../server/deploy/BeanPropertyCompound.java | 13 -- .../deploy/BeanPropertyCompoundRoot.java | 4 +- .../deploy/BeanPropertyCompoundScalar.java | 155 ++++++++-------- .../deploy/meta/DeployBeanDescriptor.java | 8 +- .../deploy/meta/DeployBeanProperty.java | 16 +- .../meta/DeployBeanPropertyCompound.java | 172 +++++++++--------- .../deploy/parse/DeployCreateProperties.java | 2 +- .../persist/dmlbind/BindableCompound.java | 53 +++--- .../persist/dmlbind/BindableProperty.java | 58 +++--- .../dmlbind/FactoryBaseProperties.java | 71 ++++---- .../BeanPropertiesReader.java} | 9 +- .../BeanPropertyGetter.java} | 4 +- .../BeanPropertyInfo.java} | 8 +- .../BeanPropertyInfoFactory.java} | 6 +- .../BeanPropertySetter.java} | 4 +- .../EnhanceBeanPropertyInfo.java} | 14 +- .../EnhanceBeanPropertyInfoFactory.java | 13 ++ .../{reflect => properties}/package.html | 0 .../reflect/EnhanceBeanReflectFactory.java | 13 -- .../server/type/CompoundTypePeriod.java | 81 +++++++++ .../server/type/DefaultTypeManager.java | 2 + .../server/type/ScalarTypeBase.java | 14 -- src/main/resources/META-INF/MANIFEST.MF | 2 +- .../tests/model/types/SomePeriodBean.java | 42 +++++ .../com/avaje/tests/types/TestPeriodType.java | 35 ++++ 27 files changed, 501 insertions(+), 333 deletions(-) rename src/main/java/com/avaje/ebeaninternal/server/{reflect/BeanReflectProperties.java => properties/BeanPropertiesReader.java} (82%) rename src/main/java/com/avaje/ebeaninternal/server/{reflect/BeanReflectGetter.java => properties/BeanPropertyGetter.java} (70%) rename src/main/java/com/avaje/ebeaninternal/server/{reflect/BeanReflect.java => properties/BeanPropertyInfo.java} (61%) rename src/main/java/com/avaje/ebeaninternal/server/{reflect/BeanReflectFactory.java => properties/BeanPropertyInfoFactory.java} (54%) rename src/main/java/com/avaje/ebeaninternal/server/{reflect/BeanReflectSetter.java => properties/BeanPropertySetter.java} (78%) rename src/main/java/com/avaje/ebeaninternal/server/{reflect/EnhanceBeanReflect.java => properties/EnhanceBeanPropertyInfo.java} (80%) create mode 100644 src/main/java/com/avaje/ebeaninternal/server/properties/EnhanceBeanPropertyInfoFactory.java rename src/main/java/com/avaje/ebeaninternal/server/{reflect => properties}/package.html (100%) delete mode 100644 src/main/java/com/avaje/ebeaninternal/server/reflect/EnhanceBeanReflectFactory.java create mode 100644 src/main/java/com/avaje/ebeaninternal/server/type/CompoundTypePeriod.java create mode 100644 src/test/java/com/avaje/tests/model/types/SomePeriodBean.java create mode 100644 src/test/java/com/avaje/tests/types/TestPeriodType.java diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java index 8cd02444b..8370f33d6 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java @@ -62,10 +62,10 @@ import com.avaje.ebeaninternal.server.deploy.parse.ReadAnnotations; import com.avaje.ebeaninternal.server.deploy.parse.TransientProperties; import com.avaje.ebeaninternal.server.idgen.UuidIdGenerator; import com.avaje.ebeaninternal.server.lib.util.Dnode; -import com.avaje.ebeaninternal.server.reflect.BeanReflect; -import com.avaje.ebeaninternal.server.reflect.BeanReflectFactory; -import com.avaje.ebeaninternal.server.reflect.BeanReflectProperties; -import com.avaje.ebeaninternal.server.reflect.EnhanceBeanReflectFactory; +import com.avaje.ebeaninternal.server.properties.BeanPropertyInfo; +import com.avaje.ebeaninternal.server.properties.BeanPropertyInfoFactory; +import com.avaje.ebeaninternal.server.properties.BeanPropertiesReader; +import com.avaje.ebeaninternal.server.properties.EnhanceBeanPropertyInfoFactory; import com.avaje.ebeaninternal.server.type.TypeManager; /** @@ -86,7 +86,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap { */ private final DeployInherit deplyInherit; - private final BeanReflectFactory reflectFactory; + private final BeanPropertyInfoFactory reflectFactory; private final DeployUtil deployUtil; @@ -1274,9 +1274,9 @@ public class BeanDescriptorManager implements BeanDescriptorMap { } } - private BeanReflectFactory createReflectionFactory() { + private BeanPropertyInfoFactory createReflectionFactory() { - return new EnhanceBeanReflectFactory(); + return new EnhanceBeanPropertyInfoFactory(); } /** @@ -1295,9 +1295,9 @@ public class BeanDescriptorManager implements BeanDescriptorMap { Class beanType = desc.getBeanType(); - BeanReflectProperties reflectProps = new BeanReflectProperties(beanType); + BeanPropertiesReader reflectProps = new BeanPropertiesReader(beanType); - BeanReflect beanReflect = reflectFactory.create(beanType); + BeanPropertyInfo beanReflect = reflectFactory.create(beanType); desc.setBeanReflect(beanReflect); desc.setProperties(reflectProps.getProperties()); diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java index fa7a5ddaf..6c0ec7c73 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java @@ -27,8 +27,8 @@ 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.query.SqlJoinType; -import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter; -import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter; +import com.avaje.ebeaninternal.server.properties.BeanPropertyGetter; +import com.avaje.ebeaninternal.server.properties.BeanPropertySetter; import com.avaje.ebeaninternal.server.text.json.WriteJson; import com.avaje.ebeaninternal.server.type.DataBind; import com.avaje.ebeaninternal.server.type.ScalarType; @@ -196,9 +196,9 @@ public class BeanProperty implements ElPropertyValue { */ final GeneratedProperty generatedProperty; - final BeanReflectGetter getter; + final BeanPropertyGetter getter; - final BeanReflectSetter setter; + final BeanPropertySetter setter; final BeanDescriptor descriptor; @@ -673,7 +673,14 @@ public class BeanProperty implements ElPropertyValue { public void setCacheDataValue(EntityBean bean, Object cacheData) { setValue(bean, cacheData); } - + + /** + * Get the property value from a compound value type. + */ + public Object getValueObject(Object bean) { + throw new RuntimeException("Expected to be called only on BeanPropertyCompoundScalar"); + } + /** * Return the value of the property method. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompound.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompound.java index 4621cef24..a080a8035 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompound.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompound.java @@ -89,19 +89,6 @@ public class BeanPropertyCompound extends BeanProperty { } } - /** - * Get the underlying compound type. - */ - @SuppressWarnings("unchecked") - public Object getValueUnderlying(EntityBean bean) { - - Object value = getValue(bean); - if (typeConverter != null){ - value = typeConverter.unwrapValue(value); - } - return value; - } - public ElPropertyValue buildElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) { if (chain == null) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundRoot.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundRoot.java index 064a862ec..018feedd0 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundRoot.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundRoot.java @@ -7,7 +7,7 @@ import java.util.List; import com.avaje.ebean.bean.EntityBean; import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty; -import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter; +import com.avaje.ebeaninternal.server.properties.BeanPropertySetter; import com.avaje.ebeaninternal.server.type.CtCompoundProperty; /** @@ -22,7 +22,7 @@ import com.avaje.ebeaninternal.server.type.CtCompoundProperty; */ public class BeanPropertyCompoundRoot { - private final BeanReflectSetter setter; + private final BeanPropertySetter setter; /** * The method used to write the property. diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundScalar.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundScalar.java index d05cf0e89..d794e306c 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundScalar.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundScalar.java @@ -6,93 +6,100 @@ import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty; import com.avaje.ebeaninternal.server.type.CtCompoundProperty; /** - * A BeanProperty owned by a Compound value object that maps to + * A BeanProperty owned by a Compound value object that maps to * a real scalar type. - * - * @author rbygrave */ public class BeanPropertyCompoundScalar extends BeanProperty { - private final BeanPropertyCompoundRoot rootProperty; - - private final CtCompoundProperty ctProperty; - - @SuppressWarnings("rawtypes") - private final ScalarTypeConverter typeConverter; - - public BeanPropertyCompoundScalar(BeanPropertyCompoundRoot rootProperty, DeployBeanProperty scalarDeploy, - CtCompoundProperty ctProperty, ScalarTypeConverter typeConverter) { - - super(scalarDeploy); - this.rootProperty = rootProperty; - this.ctProperty = ctProperty; - this.typeConverter = typeConverter; - } + private final BeanPropertyCompoundRoot rootProperty; - @SuppressWarnings("unchecked") - @Override - public Object getValue(EntityBean valueObject) { - Object val = valueObject; - if (typeConverter != null){ - val = typeConverter.unwrapValue(val); - } - return ctProperty.getValue(val); - } + private final CtCompoundProperty ctProperty; - @Override - public void setValue(EntityBean bean, Object value) { - setValueInCompound(bean, value, false); - } - - @SuppressWarnings("unchecked") - public void setValueInCompound(EntityBean bean, Object value, boolean intercept) { - - Object compoundValue = ctProperty.setValue(bean, value); - - if (compoundValue != null){ - if (typeConverter != null){ - compoundValue = typeConverter.wrapValue(compoundValue); - } - // we are at the top level and we have a compound value - // that we can set using the root property - if (intercept){ - rootProperty.setRootValueIntercept(bean, compoundValue); - } else { - rootProperty.setRootValue(bean, compoundValue); - } - } - } + @SuppressWarnings("rawtypes") + private final ScalarTypeConverter typeConverter; - /** - * No interception on embedded scalar values inside a CVO. - */ - @Override - public void setValueIntercept(EntityBean bean, Object value) { - setValueInCompound(bean, value, true); - } + public BeanPropertyCompoundScalar(BeanPropertyCompoundRoot rootProperty, DeployBeanProperty scalarDeploy, + CtCompoundProperty ctProperty, ScalarTypeConverter typeConverter) { - /** - * No interception on embedded scalar values inside a CVO. - */ - @Override - public Object getValueIntercept(EntityBean bean) { - return getValue(bean); - } + super(scalarDeploy); + this.rootProperty = rootProperty; + this.ctProperty = ctProperty; + this.typeConverter = typeConverter; + } - @Override - public Object elGetReference(EntityBean bean) { - return getValue(bean); + /** + * Return one of the scalar values from a compound type. + */ + public Object getValueObject(Object compoundValue) { + if (typeConverter != null) { + compoundValue = typeConverter.unwrapValue(compoundValue); } + return ctProperty.getValue(compoundValue); + } - @Override - public Object elGetValue(EntityBean bean) { - return getValue(bean); + @SuppressWarnings("unchecked") + @Override + public Object getValue(EntityBean valueObject) { + Object val = valueObject; + if (typeConverter != null) { + val = typeConverter.unwrapValue(val); } + return ctProperty.getValue(val); + } - @Override - public void elSetValue(EntityBean bean, Object value, boolean populate) {//, boolean reference) { - super.elSetValue(bean, value, populate); + @Override + public void setValue(EntityBean bean, Object value) { + setValueInCompound(bean, value, false); + } + + @SuppressWarnings("unchecked") + public void setValueInCompound(EntityBean bean, Object value, boolean intercept) { + + Object compoundValue = ctProperty.setValue(bean, value); + + if (compoundValue != null) { + if (typeConverter != null) { + compoundValue = typeConverter.wrapValue(compoundValue); + } + // we are at the top level and we have a compound value + // that we can set using the root property + if (intercept) { + rootProperty.setRootValueIntercept(bean, compoundValue); + } else { + rootProperty.setRootValue(bean, compoundValue); + } } + } + + /** + * No interception on embedded scalar values inside a CVO. + */ + @Override + public void setValueIntercept(EntityBean bean, Object value) { + setValueInCompound(bean, value, true); + } + + /** + * No interception on embedded scalar values inside a CVO. + */ + @Override + public Object getValueIntercept(EntityBean bean) { + return getValue(bean); + } + + @Override + public Object elGetReference(EntityBean bean) { + return getValue(bean); + } + + @Override + public Object elGetValue(EntityBean bean) { + return getValue(bean); + } + + @Override + public void elSetValue(EntityBean bean, Object value, boolean populate) {//, boolean reference) { + super.elSetValue(bean, value, populate); + } - } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java index d2be5227a..920bade18 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java @@ -36,7 +36,7 @@ import com.avaje.ebeaninternal.server.deploy.DRawSqlMeta; import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery; import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate; import com.avaje.ebeaninternal.server.deploy.InheritInfo; -import com.avaje.ebeaninternal.server.reflect.BeanReflect; +import com.avaje.ebeaninternal.server.properties.BeanPropertyInfo; /** * Describes Beans including their deployment information. @@ -127,7 +127,7 @@ public class DeployBeanDescriptor { * Used to provide mechanism to new EntityBean instances. Generated code * faster than reflection at this stage. */ - private BeanReflect beanReflect; + private BeanPropertyInfo beanReflect; private String[] properties; /** @@ -302,7 +302,7 @@ public class DeployBeanDescriptor { this.properties = props; } - public BeanReflect getBeanReflect() { + public BeanPropertyInfo getBeanReflect() { return beanReflect; } @@ -317,7 +317,7 @@ public class DeployBeanDescriptor { * Set the BeanReflect used to create new instances of an EntityBean. This * could use reflection or code generation to do this. */ - public void setBeanReflect(BeanReflect beanReflect) { + public void setBeanReflect(BeanPropertyInfo beanReflect) { this.beanReflect = beanReflect; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanProperty.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanProperty.java index 3251fb22b..39303268f 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanProperty.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanProperty.java @@ -20,8 +20,8 @@ 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.properties.BeanPropertyGetter; +import com.avaje.ebeaninternal.server.properties.BeanPropertySetter; import com.avaje.ebeaninternal.server.type.ScalarType; import com.avaje.ebeaninternal.server.type.ScalarTypeEnum; import com.avaje.ebeaninternal.server.type.ScalarTypeWrapper; @@ -202,9 +202,9 @@ public class DeployBeanProperty { private int propertyIndex; - private BeanReflectGetter getter; + private BeanPropertyGetter getter; - private BeanReflectSetter setter; + private BeanPropertySetter setter; /** * Generator for insert or update timestamp etc. @@ -439,11 +439,11 @@ public class DeployBeanProperty { this.propertyIndex = propertyIndex; } - public BeanReflectGetter getGetter() { + public BeanPropertyGetter getGetter() { return getter; } - public BeanReflectSetter getSetter() { + public BeanPropertySetter getSetter() { return setter; } @@ -482,14 +482,14 @@ public class DeployBeanProperty { /** * Set the getter used to read the property value from a bean. */ - public void setGetter(BeanReflectGetter getter) { + public void setGetter(BeanPropertyGetter getter) { this.getter = getter; } /** * Set the setter used to set the property value to a bean. */ - public void setSetter(BeanReflectSetter setter) { + public void setSetter(BeanPropertySetter setter) { this.setter = setter; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanPropertyCompound.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanPropertyCompound.java index a14ddb2b0..ebdd90acd 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanPropertyCompound.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanPropertyCompound.java @@ -21,99 +21,99 @@ import com.avaje.ebeaninternal.server.type.ScalarType; */ public class DeployBeanPropertyCompound extends DeployBeanProperty { - final CtCompoundType compoundType; + final CtCompoundType compoundType; - final ScalarTypeConverter typeConverter; + final ScalarTypeConverter typeConverter; - DeployBeanEmbedded deployEmbedded; - - /** - * Create the property. - */ - public DeployBeanPropertyCompound(DeployBeanDescriptor desc, Class targetType, - CtCompoundType compoundType, ScalarTypeConverter typeConverter) { - - super(desc, targetType, null, null); - this.compoundType = compoundType; - this.typeConverter = typeConverter; - } + DeployBeanEmbedded deployEmbedded; - public BeanPropertyCompoundRoot getFlatProperties(BeanDescriptorMap owner, BeanDescriptor descriptor) { - - // get a 'flat' list of all the scalar types, their relative property names - // and also set their matching dbColumn - - // represents the root property - BeanPropertyCompoundRoot rootProperty = new BeanPropertyCompoundRoot(this); - - // Walk the tree of a compound type collecting the - // scalar types and non-scalar properties - CtCompoundTypeScalarList ctMeta = new CtCompoundTypeScalarList(); - - compoundType.accumulateScalarTypes(null, ctMeta); - - List beanPropertyList = new ArrayList(); - - - // for each of the scalar types inside a compound value object - // build a BeanPropertyCompoundScalar with appropriate deployment - // information. - - for (Entry> entry : ctMeta.entries()) { + /** + * Create the property. + */ + public DeployBeanPropertyCompound(DeployBeanDescriptor desc, Class targetType, + CtCompoundType compoundType, ScalarTypeConverter typeConverter) { - String relativePropertyName = entry.getKey(); - ScalarType scalarType = entry.getValue(); - - CtCompoundProperty ctProp = ctMeta.getCompoundType(relativePropertyName); - - - String dbColumn = relativePropertyName.replace(".", "_"); - dbColumn = getDbColumn(relativePropertyName, dbColumn); - - DeployBeanProperty deploy = new DeployBeanProperty(null, scalarType.getType(), scalarType, null); - deploy.setScalarType(scalarType); - deploy.setDbColumn(dbColumn); - deploy.setName(relativePropertyName); - deploy.setDbInsertable(true); - deploy.setDbUpdateable(true); - deploy.setDbRead(true); - - BeanPropertyCompoundScalar bp = new BeanPropertyCompoundScalar(rootProperty, deploy, ctProp, typeConverter); - beanPropertyList.add(bp); - - rootProperty.register(bp); - } - - rootProperty.setNonScalarProperties(ctMeta.getNonScalarProperties()); - return rootProperty; - } - - private String getDbColumn(String propName, String defaultDbColumn){ - if (deployEmbedded == null){ - return defaultDbColumn; - } - String dbColumn = deployEmbedded.getPropertyColumnMap().get(propName); - return dbColumn == null ? defaultDbColumn : dbColumn; - } - - /** - * Return the deploy information specifically for the deployment - * of Embedded beans. - */ - public DeployBeanEmbedded getDeployEmbedded() { - // deployment should be single threaded - if (deployEmbedded == null){ - deployEmbedded = new DeployBeanEmbedded(); - } - return deployEmbedded; - } + super(desc, targetType, null, null); + this.compoundType = compoundType; + this.typeConverter = typeConverter; + } - public ScalarTypeConverter getTypeConverter() { - return typeConverter; + public BeanPropertyCompoundRoot getFlatProperties(BeanDescriptorMap owner, BeanDescriptor descriptor) { + + // get a 'flat' list of all the scalar types, their relative property names + // and also set their matching dbColumn + + // represents the root property + BeanPropertyCompoundRoot rootProperty = new BeanPropertyCompoundRoot(this); + + // Walk the tree of a compound type collecting the + // scalar types and non-scalar properties + CtCompoundTypeScalarList ctMeta = new CtCompoundTypeScalarList(); + + compoundType.accumulateScalarTypes(null, ctMeta); + + List beanPropertyList = new ArrayList(); + + + // for each of the scalar types inside a compound value object + // build a BeanPropertyCompoundScalar with appropriate deployment + // information. + + for (Entry> entry : ctMeta.entries()) { + + String relativePropertyName = entry.getKey(); + ScalarType scalarType = entry.getValue(); + + CtCompoundProperty ctProp = ctMeta.getCompoundType(relativePropertyName); + + + String dbColumn = (getName() + "." + relativePropertyName).replace(".", "_"); + dbColumn = getDbColumn(relativePropertyName, dbColumn); + + DeployBeanProperty deploy = new DeployBeanProperty(null, scalarType.getType(), scalarType, null); + deploy.setScalarType(scalarType); + deploy.setDbColumn(dbColumn); + deploy.setName(relativePropertyName); + deploy.setDbInsertable(true); + deploy.setDbUpdateable(true); + deploy.setDbRead(true); + + BeanPropertyCompoundScalar bp = new BeanPropertyCompoundScalar(rootProperty, deploy, ctProp, typeConverter); + beanPropertyList.add(bp); + + rootProperty.register(bp); } - public CtCompoundType getCompoundType() { - return compoundType; + rootProperty.setNonScalarProperties(ctMeta.getNonScalarProperties()); + return rootProperty; + } + + private String getDbColumn(String propName, String defaultDbColumn) { + if (deployEmbedded == null) { + return defaultDbColumn; } + String dbColumn = deployEmbedded.getPropertyColumnMap().get(propName); + return dbColumn == null ? defaultDbColumn : dbColumn; + } + + /** + * Return the deploy information specifically for the deployment + * of Embedded beans. + */ + public DeployBeanEmbedded getDeployEmbedded() { + // deployment should be single threaded + if (deployEmbedded == null) { + deployEmbedded = new DeployBeanEmbedded(); + } + return deployEmbedded; + } + + public ScalarTypeConverter getTypeConverter() { + return typeConverter; + } + + public CtCompoundType getCompoundType() { + return compoundType; + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/DeployCreateProperties.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/DeployCreateProperties.java index ad5674de4..024f2bf66 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/DeployCreateProperties.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/DeployCreateProperties.java @@ -93,7 +93,7 @@ public class DeployCreateProperties { } /** - * reflect the bean properties from Class. Some of these properties may not map to database + * properties the bean properties from Class. Some of these properties may not map to database * columns. */ private void createProperties(DeployBeanDescriptor desc, Class beanType, int level) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/BindableCompound.java b/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/BindableCompound.java index f11467f16..a70604b29 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/BindableCompound.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/BindableCompound.java @@ -14,40 +14,41 @@ import com.avaje.ebeaninternal.server.persist.dml.GenerateDmlRequest; */ public class BindableCompound implements Bindable { - private final Bindable[] items; + private final BindableProperty[] items; - private final BeanPropertyCompound compound; + private final BeanPropertyCompound compound; - public BindableCompound(BeanPropertyCompound embProp, List list) { - this.compound = embProp; - this.items = list.toArray(new Bindable[list.size()]); + public BindableCompound(BeanPropertyCompound embProp, List list) { + this.compound = embProp; + this.items = list.toArray(new BindableProperty[list.size()]); + } + + public String toString() { + return "BindableCompound " + compound + " items:" + Arrays.toString(items); + } + + public void dmlAppend(GenerateDmlRequest request) { + + for (int i = 0; i < items.length; i++) { + items[i].dmlAppend(request); } + } - public String toString() { - return "BindableCompound " + compound + " items:" + Arrays.toString(items); + public void addToUpdate(PersistRequestBean request, List list) { + if (request.isAddToUpdate(compound)) { + list.add(this); } + } - public void dmlAppend(GenerateDmlRequest request) { + public void dmlBind(BindableRequest bindRequest, EntityBean bean) throws SQLException { - for (int i = 0; i < items.length; i++) { - items[i].dmlAppend(request); - } - } + // get the compound type value + Object valueObject = compound.getValue(bean); - public void addToUpdate(PersistRequestBean request, List list) { - if (request.isAddToUpdate(compound)) { - list.add(this); - } - } - - public void dmlBind(BindableRequest bindRequest, EntityBean bean) throws SQLException { - - throw new RuntimeException("This is broken, need to break out the scalar values!!"); - - //Object valueObject = compound.getValue(bean); - //for (int i = 0; i < items.length; i++) { - // items[i].dmlBind(bindRequest, valueObject); - //} + // bind each of the underlying scalar values for this compound type + for (int i = 0; i < items.length; i++) { + items[i].dmlBindObject(bindRequest, valueObject); } + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/BindableProperty.java b/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/BindableProperty.java index 56f709ffc..3b84078d0 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/BindableProperty.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/BindableProperty.java @@ -13,33 +13,47 @@ import com.avaje.ebeaninternal.server.persist.dml.GenerateDmlRequest; */ public class BindableProperty implements Bindable { - protected final BeanProperty prop; + protected final BeanProperty prop; - public BindableProperty(BeanProperty prop) { - this.prop = prop; + public BindableProperty(BeanProperty prop) { + this.prop = prop; + } + + public String toString() { + return prop.toString(); + } + + public void addToUpdate(PersistRequestBean request, List list) { + if (request.isAddToUpdate(prop)) { + list.add(this); } + } - public String toString() { - return prop.toString(); + public void dmlAppend(GenerateDmlRequest request) { + request.appendColumn(prop.getDbColumn()); + } + + /** + * Normal binding of a property value from the bean. + */ + public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException { + + Object value = null; + if (bean != null) { + value = prop.getValue(bean); } + request.bind(value, prop, prop.getName()); + } - public void addToUpdate(PersistRequestBean request, List list) { - if (request.isAddToUpdate(prop)) { - list.add(this); - } - } + /** + * For compound types bind one of the underlying scalar values for a compound type. + */ + public void dmlBindObject(BindableRequest request, Object bean) throws SQLException { - public void dmlAppend(GenerateDmlRequest request) { - request.appendColumn(prop.getDbColumn()); - } - - public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException { - - Object value = null; - if (bean != null) { - value = prop.getValue(bean); - } - // value = prop.getDefaultValue(); - request.bind(value, prop, prop.getName()); + Object value = null; + if (bean != null) { + value = prop.getValueObject(bean); } + request.bind(value, prop, prop.getName()); + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/FactoryBaseProperties.java b/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/FactoryBaseProperties.java index 4b3614979..69de1e8f1 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/FactoryBaseProperties.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/FactoryBaseProperties.java @@ -16,49 +16,52 @@ import com.avaje.ebeaninternal.server.persist.dml.DmlMode; */ public class FactoryBaseProperties { - private final FactoryProperty factoryProperty; - - - public FactoryBaseProperties(boolean bindEncryptDataFirst) { - factoryProperty = new FactoryProperty(bindEncryptDataFirst); - } + private final FactoryProperty factoryProperty; - /** - * Add Bindable for the base properties to the list. - */ - public void create(List list, BeanDescriptor desc, DmlMode mode, boolean withLobs) { - add(desc.propertiesBaseScalar(), list, desc, mode, withLobs); + public FactoryBaseProperties(boolean bindEncryptDataFirst) { + factoryProperty = new FactoryProperty(bindEncryptDataFirst); + } - BeanPropertyCompound[] compoundProps = desc.propertiesBaseCompound(); - for (int i = 0; i < compoundProps.length; i++) { - BeanProperty[] props = compoundProps[i].getScalarProperties(); + /** + * Add Bindable for the base properties to the list. + */ + public void create(List list, BeanDescriptor desc, DmlMode mode, boolean withLobs) { - ArrayList newList = new ArrayList(props.length); - add(props, newList, desc, mode, withLobs); - - BindableCompound compoundBindable = new BindableCompound(compoundProps[i], newList); + add(desc.propertiesBaseScalar(), list, desc, mode, withLobs); - list.add(compoundBindable); - } - } + BeanPropertyCompound[] compoundProps = desc.propertiesBaseCompound(); + for (int i = 0; i < compoundProps.length; i++) { + BeanProperty[] props = compoundProps[i].getScalarProperties(); - private void add(BeanProperty[] props, List list, BeanDescriptor desc, DmlMode mode, boolean withLobs) { + List newList = new ArrayList(props.length); + addCompound(props, newList, desc, mode, withLobs); - for (int i = 0; i < props.length; i++) { + BindableCompound compoundBindable = new BindableCompound(compoundProps[i], newList); -// if(DmlMode.WHERE.equals(mode) && !withLobs && !props[i].isDbUpdatable()) { -// // skip non-updatable column from where clause -// } else { - Bindable item = factoryProperty.create(props[i], mode, withLobs); - if (item != null) { - list.add(item); - } else { - // null where readOnly (Secondary tables) or Lob exclusion - } -// } - } + list.add(compoundBindable); + } + } + private void add(BeanProperty[] props, List list, BeanDescriptor desc, DmlMode mode, boolean withLobs) { + + for (int i = 0; i < props.length; i++) { + Bindable item = factoryProperty.create(props[i], mode, withLobs); + if (item != null) { + list.add(item); + } + } + } + + private void addCompound(BeanProperty[] props, List list, BeanDescriptor desc, DmlMode mode, boolean withLobs) { + + for (int i = 0; i < props.length; i++) { + BindableProperty item = (BindableProperty) factoryProperty.create(props[i], mode, withLobs); + if (item != null) { + list.add(item); + } } + } + } diff --git a/src/main/java/com/avaje/ebeaninternal/server/reflect/BeanReflectProperties.java b/src/main/java/com/avaje/ebeaninternal/server/properties/BeanPropertiesReader.java similarity index 82% rename from src/main/java/com/avaje/ebeaninternal/server/reflect/BeanReflectProperties.java rename to src/main/java/com/avaje/ebeaninternal/server/properties/BeanPropertiesReader.java index ac0fa94cd..abda15c40 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/reflect/BeanReflectProperties.java +++ b/src/main/java/com/avaje/ebeaninternal/server/properties/BeanPropertiesReader.java @@ -1,17 +1,20 @@ -package com.avaje.ebeaninternal.server.reflect; +package com.avaje.ebeaninternal.server.properties; import java.lang.reflect.Field; import java.util.Arrays; import java.util.HashMap; import java.util.Map; -public class BeanReflectProperties { +/** + * Determines the properties on a given bean. + */ +public class BeanPropertiesReader { private final Map propertyIndexMap = new HashMap(); private final String[] props; - public BeanReflectProperties(Class clazz) { + public BeanPropertiesReader(Class clazz) { this.props = getProperties(clazz); for (int i=0; i */ -public interface BeanReflect { +public interface BeanPropertyInfo { /** * Create an EntityBean for this type. @@ -17,10 +17,10 @@ public interface BeanReflect { /** * Return the getter for a given bean property. */ - public BeanReflectGetter getGetter(String name, int position); + public BeanPropertyGetter getGetter(String name, int position); /** * Return the setter for a given bean property. */ - public BeanReflectSetter getSetter(String name, int position); + public BeanPropertySetter getSetter(String name, int position); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/reflect/BeanReflectFactory.java b/src/main/java/com/avaje/ebeaninternal/server/properties/BeanPropertyInfoFactory.java similarity index 54% rename from src/main/java/com/avaje/ebeaninternal/server/reflect/BeanReflectFactory.java rename to src/main/java/com/avaje/ebeaninternal/server/properties/BeanPropertyInfoFactory.java index 1b897032a..76ecc9e5f 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/reflect/BeanReflectFactory.java +++ b/src/main/java/com/avaje/ebeaninternal/server/properties/BeanPropertyInfoFactory.java @@ -1,14 +1,14 @@ -package com.avaje.ebeaninternal.server.reflect; +package com.avaje.ebeaninternal.server.properties; /** * Creates BeanReflect object used to provide getter setter and construction * for the beans. */ -public interface BeanReflectFactory { +public interface BeanPropertyInfoFactory { /** * Create the BeanReflect for the given plain bean and its EntityBean equivalent. */ - public BeanReflect create(Class entityBeanType); + public BeanPropertyInfo create(Class entityBeanType); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/reflect/BeanReflectSetter.java b/src/main/java/com/avaje/ebeaninternal/server/properties/BeanPropertySetter.java similarity index 78% rename from src/main/java/com/avaje/ebeaninternal/server/reflect/BeanReflectSetter.java rename to src/main/java/com/avaje/ebeaninternal/server/properties/BeanPropertySetter.java index 614408a6e..9d93f6c7e 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/reflect/BeanReflectSetter.java +++ b/src/main/java/com/avaje/ebeaninternal/server/properties/BeanPropertySetter.java @@ -1,11 +1,11 @@ -package com.avaje.ebeaninternal.server.reflect; +package com.avaje.ebeaninternal.server.properties; import com.avaje.ebean.bean.EntityBean; /** * The setter for a given bean property. */ -public interface BeanReflectSetter { +public interface BeanPropertySetter { /** * Set the property value of a bean. diff --git a/src/main/java/com/avaje/ebeaninternal/server/reflect/EnhanceBeanReflect.java b/src/main/java/com/avaje/ebeaninternal/server/properties/EnhanceBeanPropertyInfo.java similarity index 80% rename from src/main/java/com/avaje/ebeaninternal/server/reflect/EnhanceBeanReflect.java rename to src/main/java/com/avaje/ebeaninternal/server/properties/EnhanceBeanPropertyInfo.java index 3749431ee..4a0f6fc60 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/reflect/EnhanceBeanReflect.java +++ b/src/main/java/com/avaje/ebeaninternal/server/properties/EnhanceBeanPropertyInfo.java @@ -1,4 +1,4 @@ -package com.avaje.ebeaninternal.server.reflect; +package com.avaje.ebeaninternal.server.properties; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; @@ -11,13 +11,13 @@ import com.avaje.ebean.bean.EntityBean; * A BeanReflect implementation based on the enhancement that creates EntityBean * implementations. */ -public final class EnhanceBeanReflect implements BeanReflect { +public final class EnhanceBeanPropertyInfo implements BeanPropertyInfo { private static final Object[] constuctorArgs = new Object[0]; private final Constructor constructor; - public EnhanceBeanReflect(Class clazz) { + public EnhanceBeanPropertyInfo(Class clazz) { try { if (Modifier.isAbstract(clazz.getModifiers())) { this.constructor = null; @@ -47,15 +47,15 @@ public final class EnhanceBeanReflect implements BeanReflect { } } - public BeanReflectGetter getGetter(String name, int position) { + public BeanPropertyGetter getGetter(String name, int position) { return new Getter(position); } - public BeanReflectSetter getSetter(String name, int position) { + public BeanPropertySetter getSetter(String name, int position) { return new Setter(position); } - static final class Getter implements BeanReflectGetter { + static final class Getter implements BeanPropertyGetter { private final int fieldIndex; @@ -72,7 +72,7 @@ public final class EnhanceBeanReflect implements BeanReflect { } } - static final class Setter implements BeanReflectSetter { + static final class Setter implements BeanPropertySetter { private final int fieldIndex; diff --git a/src/main/java/com/avaje/ebeaninternal/server/properties/EnhanceBeanPropertyInfoFactory.java b/src/main/java/com/avaje/ebeaninternal/server/properties/EnhanceBeanPropertyInfoFactory.java new file mode 100644 index 000000000..d70911890 --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/properties/EnhanceBeanPropertyInfoFactory.java @@ -0,0 +1,13 @@ +package com.avaje.ebeaninternal.server.properties; + +/** + * Creates a BeanReflectFactory based on the enhancement that + * creates EntityBean implementations. + */ +public final class EnhanceBeanPropertyInfoFactory implements BeanPropertyInfoFactory { + + public BeanPropertyInfo create(Class entityBeanType) { + return new EnhanceBeanPropertyInfo(entityBeanType); + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/reflect/package.html b/src/main/java/com/avaje/ebeaninternal/server/properties/package.html similarity index 100% rename from src/main/java/com/avaje/ebeaninternal/server/reflect/package.html rename to src/main/java/com/avaje/ebeaninternal/server/properties/package.html diff --git a/src/main/java/com/avaje/ebeaninternal/server/reflect/EnhanceBeanReflectFactory.java b/src/main/java/com/avaje/ebeaninternal/server/reflect/EnhanceBeanReflectFactory.java deleted file mode 100644 index 401d2b72c..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/reflect/EnhanceBeanReflectFactory.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.avaje.ebeaninternal.server.reflect; - -/** - * Creates a BeanReflectFactory based on the enhancement that - * creates EntityBean implementations. - */ -public final class EnhanceBeanReflectFactory implements BeanReflectFactory { - - public BeanReflect create(Class entityBeanType) { - return new EnhanceBeanReflect(entityBeanType); - } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/CompoundTypePeriod.java b/src/main/java/com/avaje/ebeaninternal/server/type/CompoundTypePeriod.java new file mode 100644 index 000000000..2209b470b --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/type/CompoundTypePeriod.java @@ -0,0 +1,81 @@ +package com.avaje.ebeaninternal.server.type; + +import com.avaje.ebean.config.CompoundType; +import com.avaje.ebean.config.CompoundTypeProperty; + +import java.time.Period; + +/** + * Compound type for Period value type. + *

+ * Persists the Period into 3 separate integer columns for years, months and days. + *

+ */ +public class CompoundTypePeriod implements CompoundType { + + CompoundTypeProperty[] properties = new CompoundTypeProperty[3]; + + public CompoundTypePeriod() { + properties[0] = new CTPeriodYear(); + properties[1] = new CTPeriodMonth(); + properties[2] = new CTPeriodDay(); + } + + @Override + public Period create(Object[] propertyValues) { + return Period.of((Integer)propertyValues[0], (Integer)propertyValues[1], (Integer)propertyValues[2]); + } + + @Override + public CompoundTypeProperty[] getProperties() { + return properties; + } + + static class CTPeriodYear implements CompoundTypeProperty { + + public String getName() { + return "years"; + } + + public Integer getValue(Period valueObject) { + return valueObject.getYears(); + } + + public int getDbType() { + return 0; + } + + } + + static class CTPeriodMonth implements CompoundTypeProperty { + + public String getName() { + return "months"; + } + + public Integer getValue(Period valueObject) { + return valueObject.getMonths(); + } + + public int getDbType() { + return 0; + } + + } + + static class CTPeriodDay implements CompoundTypeProperty { + + public String getName() { + return "days"; + } + + public Integer getValue(Period valueObject) { + return valueObject.getDays(); + } + + public int getDbType() { + return 0; + } + + } +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/DefaultTypeManager.java b/src/main/java/com/avaje/ebeaninternal/server/type/DefaultTypeManager.java index 39cd6ae16..568b5227d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/DefaultTypeManager.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/DefaultTypeManager.java @@ -616,6 +616,8 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable { typeMap.put(ZoneId.class, new ScalarTypeZoneId()); typeMap.put(ZoneOffset.class, new ScalarTypeZoneOffset()); + createCompoundScalarDataReader(Period.class, new CompoundTypePeriod(), ""); + boolean localTimeNanos = config.isLocalTimeWithNanos(); typeMap.put(java.time.LocalTime.class, (localTimeNanos)? new ScalarTypeLocalTimeWithNanos() : new ScalarTypeLocalTime()); diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBase.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBase.java index fddfc4d25..97dcff747 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBase.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBase.java @@ -57,20 +57,6 @@ public abstract class ScalarTypeBase implements ScalarType { return formatValue((T) v); } - /** - * Return true if the value is null. - */ - public boolean isDbNull(Object value) { - return value == null; - } - - /** - * Returns the value that was passed in. - */ - public Object getDbNullValue(Object value) { - return value; - } - public void loadIgnore(DataReader dataReader) { dataReader.incrementPos(1); } diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF index 75f2ae544..e76e941dd 100644 --- a/src/main/resources/META-INF/MANIFEST.MF +++ b/src/main/resources/META-INF/MANIFEST.MF @@ -49,7 +49,7 @@ Export-Package: com.avaje.ebean, com.avaje.ebeaninternal.server.persist.dmlbind, com.avaje.ebeaninternal.server.query, com.avaje.ebeaninternal.server.querydefn, - com.avaje.ebeaninternal.server.reflect, + com.avaje.ebeaninternal.server.properties, com.avaje.ebeaninternal.server.resource, com.avaje.ebeaninternal.server.text.csv, com.avaje.ebeaninternal.server.text.json, diff --git a/src/test/java/com/avaje/tests/model/types/SomePeriodBean.java b/src/test/java/com/avaje/tests/model/types/SomePeriodBean.java new file mode 100644 index 000000000..c93cd4f9c --- /dev/null +++ b/src/test/java/com/avaje/tests/model/types/SomePeriodBean.java @@ -0,0 +1,42 @@ +package com.avaje.tests.model.types; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Version; +import java.time.*; + +@Entity +public class SomePeriodBean { + + @Id + Long id; + + @Version + Long version; + + Period period; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + public Period getPeriod() { + return period; + } + + public void setPeriod(Period period) { + this.period = period; + } +} diff --git a/src/test/java/com/avaje/tests/types/TestPeriodType.java b/src/test/java/com/avaje/tests/types/TestPeriodType.java new file mode 100644 index 000000000..c1838fcd5 --- /dev/null +++ b/src/test/java/com/avaje/tests/types/TestPeriodType.java @@ -0,0 +1,35 @@ +package com.avaje.tests.types; + +import com.avaje.ebean.BaseTestCase; +import com.avaje.ebean.Ebean; +import com.avaje.tests.model.types.SomePeriodBean; +import org.junit.Test; + +import java.time.Period; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + */ +public class TestPeriodType extends BaseTestCase { + + @Test + public void testInsert() { + + SomePeriodBean bean = new SomePeriodBean(); + bean.setPeriod(Period.of(3, 4, 5)); + Ebean.save(bean); + + SomePeriodBean bean1 = Ebean.find(SomePeriodBean.class, bean.getId()); + assertEquals(bean.getPeriod(), bean1.getPeriod()); + + // insert fetch null value + SomePeriodBean bean2 = new SomePeriodBean(); + Ebean.save(bean2); + + SomePeriodBean bean3 = Ebean.find(SomePeriodBean.class, bean2.getId()); + assertNull(bean3.getPeriod()); + } + +}