diff --git a/src/main/java/com/avaje/ebean/plugin/BeanType.java b/src/main/java/com/avaje/ebean/plugin/BeanType.java
index 79d6c784d..3e19ca804 100644
--- a/src/main/java/com/avaje/ebean/plugin/BeanType.java
+++ b/src/main/java/com/avaje/ebean/plugin/BeanType.java
@@ -6,6 +6,7 @@ import com.avaje.ebean.event.BeanPersistController;
import com.avaje.ebean.event.BeanPersistListener;
import com.avaje.ebean.event.BeanQueryAdapter;
import com.avaje.ebean.text.json.JsonReadOptions;
+import com.avaje.ebeaninternal.api.SpiQuery;
import com.avaje.ebeanservice.docstore.api.mapping.DocumentMapping;
import com.fasterxml.jackson.core.JsonParser;
@@ -17,6 +18,11 @@ import java.util.Collection;
*/
public interface BeanType {
+ /**
+ * Return the short name of the bean type.
+ */
+ String getName();
+
/**
* Return the full name of the bean type.
*/
@@ -53,12 +59,12 @@ public interface BeanType {
Property getWhenCreatedProperty();
/**
- * Return the SpiProperty for a property to read values from a bean.
+ * Return the Property to read values from a bean.
*/
Property getProperty(String propertyName);
/**
- * Return the SpiExpressionPath for a given property path.
+ * Return the ExpressionPath for a given property path.
*
* This can return a property or nested property path.
*
@@ -154,4 +160,28 @@ public interface BeanType {
*/
T jsonRead(JsonParser parser, JsonReadOptions readOptions, Object objectMapper) throws IOException;
+ /**
+ * Add the discriminator value to the query if needed.
+ */
+ void addInheritanceWhere(SpiQuery> query);
+
+ /**
+ * Return the root bean type for an inheritance hierarchy.
+ */
+ BeanType> root();
+
+ /**
+ * Return true if this bean type has an inheritance hierarchy.
+ */
+ boolean hasInheritance();
+
+ /**
+ * Return the discriminator column.
+ */
+ String getDiscColumn();
+
+ /**
+ * Create a bean given the discriminator value.
+ */
+ T createBeanUsingDisc(Object discValue);
}
diff --git a/src/main/java/com/avaje/ebean/plugin/ExpressionPath.java b/src/main/java/com/avaje/ebean/plugin/ExpressionPath.java
index e1ef6fbcb..8f529c64e 100644
--- a/src/main/java/com/avaje/ebean/plugin/ExpressionPath.java
+++ b/src/main/java/com/avaje/ebean/plugin/ExpressionPath.java
@@ -1,5 +1,7 @@
package com.avaje.ebean.plugin;
+import com.avaje.ebean.text.StringParser;
+
/**
* A dot notation expression path.
*/
@@ -10,11 +12,46 @@ public interface ExpressionPath {
*/
boolean containsMany();
+ /**
+ * Return the value from a given entity bean.
+ */
+ Object pathGet(Object bean);
+
/**
* Set a value to the bean for this expression path.
*
* @param bean the bean to set the value on
* @param value the value to set
*/
- void set(Object bean, Object value);
+ void pathSet(Object bean, Object value);
+
+ /**
+ * Convert the value to the expected type.
+ *
+ * Typically useful for converting strings to the appropriate number type etc.
+ *
+ */
+ Object convert(Object value);
+
+ /**
+ * Return the default StringParser for the scalar property.
+ */
+ StringParser getStringParser();
+
+ /**
+ * For DateTime capable scalar types convert the long systemTimeMillis into
+ * an appropriate java time (Date,Timestamp,Time,Calendar, JODA type etc).
+ */
+ Object parseDateTime(long systemTimeMillis);
+
+ /**
+ * Return true if the last type is "DateTime capable" - can support
+ * {@link #parseDateTime(long)}.
+ */
+ boolean isDateTimeCapable();
+
+ /**
+ * Return the underlying JDBC type or 0 if this is not a scalar type.
+ */
+ int getJdbcType();
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java
index 11a16db0b..501de1285 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java
@@ -309,7 +309,7 @@ public final class PersistRequestBean extends PersistRequest implements BeanP
*/
private boolean isDocStoreNotify() {
// Either queue or directly update the document store
- return docStoreMode != DocStoreMode.IGNORE;
+ return docStoreMode != DocStoreMode.IGNORE || beanDescriptor.docStoreAdapter().hasEmbeddedInvalidation();
}
public boolean isNotifyPersistListener() {
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java
index 2aa19e6fe..c949f2836 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java
@@ -71,6 +71,8 @@ import com.avaje.ebeanservice.docstore.api.DocStoreBeanAdapter;
import com.avaje.ebeanservice.docstore.api.DocStoreUpdateContext;
import com.avaje.ebeanservice.docstore.api.DocStoreUpdates;
import com.avaje.ebeanservice.docstore.api.mapping.DocMappingBuilder;
+import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyMapping;
+import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyType;
import com.avaje.ebeanservice.docstore.api.mapping.DocumentMapping;
import com.fasterxml.jackson.core.JsonParser;
import org.slf4j.Logger;
@@ -80,6 +82,7 @@ import javax.persistence.PersistenceException;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.sql.SQLException;
+import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -358,12 +361,12 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
private final String docStoreQueueId;
- private DocumentMapping docMapping;
-
private final BeanDescriptorDraftHelp draftHelp;
private final BeanDescriptorCacheHelp cacheHelp;
private final BeanDescriptorJsonHelp jsonHelp;
- private final DocStoreBeanAdapter docStoreAdapter;
+ private DocStoreBeanAdapter docStoreAdapter;
+ private DocumentMapping docMapping;
+
private final String defaultSelectClause;
@@ -680,7 +683,6 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
namedUpdate.initialise(parser);
}
}
- docStoreAdapter.registerPaths();
}
/**
@@ -690,7 +692,11 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
for (int i = 0; i < propertiesMany.length; i++) {
propertiesMany[i].initialisePostTarget();
}
+ if (inheritInfo != null && !inheritInfo.isRoot()) {
+ docStoreAdapter = (DocStoreBeanAdapter)inheritInfo.getRoot().getBeanDescriptor().docStoreAdapter();
+ }
docMapping = docStoreAdapter.createDocMapping();
+ docStoreAdapter.registerPaths();
}
public void initInheritInfo() {
@@ -932,16 +938,44 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
/**
* Build the Document mapping recursively with the given prefix relative to the root of the document.
*/
- public void docStoreMapping(DocMappingBuilder mapping, String prefix) {
+ public void docStoreMapping(final DocMappingBuilder mapping, final String prefix) {
if (prefix != null && idProperty != null) {
// id property not included in the
idProperty.docStoreMapping(mapping, prefix);
}
+ if (inheritInfo != null) {
+ String discCol = inheritInfo.getDiscriminatorColumn();
+ if (Types.VARCHAR == inheritInfo.getDiscriminatorType()) {
+ mapping.add(new DocPropertyMapping(discCol, DocPropertyType.ENUM));
+ } else {
+ mapping.add(new DocPropertyMapping(discCol, DocPropertyType.INTEGER));
+ }
+ }
for (BeanProperty prop: propertiesNonTransient) {
prop.docStoreMapping(mapping, prefix);
}
+ if (inheritInfo != null) {
+ inheritInfo.visitChildren(new InheritInfoVisitor() {
+ @Override
+ public void visit(InheritInfo inheritInfo) {
+ for (BeanProperty localProperty : inheritInfo.localProperties()) {
+ localProperty.docStoreMapping(mapping, prefix);
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Return the root bean type if part of inheritance hierarchy.
+ */
+ public BeanType> root() {
+ if (inheritInfo != null && !inheritInfo.isRoot()) {
+ return inheritInfo.getRoot().getBeanDescriptor();
+ }
+ return this;
}
/**
@@ -1539,7 +1573,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
}
String[] splitBegin = SplitName.splitBegin(path);
- BeanProperty beanProperty = propMap.get(splitBegin[0]);
+ BeanProperty beanProperty = findBeanProperty(splitBegin[0]);
if (beanProperty instanceof BeanPropertyAssoc>) {
BeanPropertyAssoc> assocProp = (BeanPropertyAssoc>) beanProperty;
return assocProp.getTargetDescriptor().getBeanDescriptor(splitBegin[1]);
@@ -1709,7 +1743,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
@Override
public Property getProperty(String propName) {
- return getBeanProperty(propName);
+ return findBeanProperty(propName);
}
/**
@@ -1976,6 +2010,30 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
return inheritInfo;
}
+ @Override
+ public boolean hasInheritance() {
+ return inheritInfo != null;
+ }
+
+ @Override
+ public String getDiscColumn() {
+ return inheritInfo.getDiscriminatorColumn();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public T createBeanUsingDisc(Object discValue) {
+ InheritInfo type = inheritInfo.getType(discValue.toString());
+ return (T)type.getBeanDescriptor().createBean();
+ }
+
+ @Override
+ public void addInheritanceWhere(SpiQuery> query) {
+ if (inheritInfo != null && !inheritInfo.isRoot()) {
+ query.where().eq(inheritInfo.getDiscriminatorColumn(), inheritInfo.getDiscriminatorValue());
+ }
+ }
+
/**
* Return true if this is an embedded bean.
*/
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanFkeyProperty.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanFkeyProperty.java
index 15521d4a4..27b8a118b 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanFkeyProperty.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanFkeyProperty.java
@@ -162,23 +162,22 @@ public final class BeanFkeyProperty implements ElPropertyValue {
throw new RuntimeException("ElPropertyDeploy only - not implemented");
}
- public Object elConvertType(Object value) {
+ @Override
+ public Object convert(Object value) {
throw new RuntimeException("ElPropertyDeploy only - not implemented");
}
@Override
- public void set(Object bean, Object value) {
+ public void pathSet(Object bean, Object value) {
throw new RuntimeException("ElPropertyDeploy only - not implemented");
}
- public void elSetValue(EntityBean bean, Object value, boolean populate) {
- throw new RuntimeException("ElPropertyDeploy only - not implemented");
- }
-
- public Object elGetValue(EntityBean bean) {
+ @Override
+ public Object pathGet(Object bean) {
throw new RuntimeException("ElPropertyDeploy only - not implemented");
}
+ @Override
public Object elGetReference(EntityBean bean) {
throw new RuntimeException("ElPropertyDeploy only - not implemented");
}
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 3c8b6e112..8defbe7af 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java
@@ -767,7 +767,7 @@ public class BeanProperty implements ElPropertyValue, Property {
}
}
- public Object elConvertType(Object value) {
+ public Object convert(Object value) {
if (value == null) {
return null;
}
@@ -775,25 +775,20 @@ public class BeanProperty implements ElPropertyValue, Property {
}
@Override
- public void set(Object bean, Object value) {
+ public void pathSet(Object bean, Object value) {
- // convert for Enums etc
- Object logicalVal = convertToLogicalType(value);
- elSetValue((EntityBean) bean, logicalVal, true);
- }
-
- public void elSetValue(EntityBean bean, Object value, boolean populate) {
if (bean != null) {
- // Not using setValueIntercept at this stage
- setValue(bean, value);
+ Object logicalVal = convertToLogicalType(value);
+ setValue((EntityBean)bean, logicalVal);
}
}
- public Object elGetValue(EntityBean bean) {
+ @Override
+ public Object pathGet(Object bean) {
if (bean == null) {
return null;
}
- return getValueIntercept(bean);
+ return getValueIntercept((EntityBean)bean);
}
public Object elGetReference(EntityBean bean) {
@@ -1330,7 +1325,7 @@ public class BeanProperty implements ElPropertyValue, Property {
* Return true if this is a String Id property and should be treated as a code by the document store.
*/
private boolean isStringId(DocPropertyType type) {
- return DocPropertyType.STRING == type && id;
+ return DocPropertyType.STRING == type && (id || discriminator);
}
}
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 d3fa6b68b..285afe984 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundScalar.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundScalar.java
@@ -77,8 +77,8 @@ public class BeanPropertyCompoundScalar extends BeanProperty {
}
@Override
- public Object elGetValue(EntityBean bean) {
- return getValue(bean);
+ public Object pathGet(Object bean) {
+ return ctProperty.getValue(bean);
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/InheritInfo.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/InheritInfo.java
index b85c6c1f0..28ba06a7d 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/InheritInfo.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/InheritInfo.java
@@ -145,6 +145,13 @@ public class InheritInfo {
return descriptor;
}
+ /**
+ * Return the local properties for this node in the hierarchy.
+ */
+ public BeanProperty[] localProperties() {
+ return descriptor.propertiesLocal();
+ }
+
/**
* Get the bean property additionally looking in the sub types.
*/
diff --git a/src/main/java/com/avaje/ebeaninternal/server/el/ElComparatorProperty.java b/src/main/java/com/avaje/ebeaninternal/server/el/ElComparatorProperty.java
index 6348fd5cc..54aeb0b1b 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/el/ElComparatorProperty.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/el/ElComparatorProperty.java
@@ -2,8 +2,6 @@ package com.avaje.ebeaninternal.server.el;
import java.util.Comparator;
-import com.avaje.ebean.bean.EntityBean;
-
/**
* Comparator based on a ElGetValue.
*/
@@ -23,16 +21,14 @@ public final class ElComparatorProperty implements Comparator, ElComparato
public int compare(T o1, T o2) {
- Object val1 = elGetValue.elGetValue((EntityBean) o1);
- Object val2 = elGetValue.elGetValue((EntityBean) o2);
-
+ Object val1 = elGetValue.pathGet(o1);
+ Object val2 = elGetValue.pathGet(o2);
return compareValues(val1, val2);
}
public int compareValue(Object value, T o2) {
- Object val2 = elGetValue.elGetValue((EntityBean) o2);
-
+ Object val2 = elGetValue.pathGet(o2);
return compareValues(value, val2);
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/el/ElFilter.java b/src/main/java/com/avaje/ebeaninternal/server/el/ElFilter.java
index d65fe8eb4..9ef9a520c 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/el/ElFilter.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/el/ElFilter.java
@@ -28,7 +28,7 @@ public final class ElFilter implements Filter {
private Object convertValue(String propertyName, Object value) {
// convert type of value to match expected type
ElPropertyValue elGetValue = beanDescriptor.getElGetValue(propertyName);
- return elGetValue.elConvertType(value);
+ return elGetValue.convert(value);
}
private ElComparator getElComparator(String propertyName) {
@@ -87,8 +87,8 @@ public final class ElFilter implements Filter {
public Filter between(String propertyName, Object min, Object max) {
ElPropertyValue elGetValue = getElGetValue(propertyName);
- min = elGetValue.elConvertType(min);
- max = elGetValue.elConvertType(max);
+ min = elGetValue.convert(min);
+ max = elGetValue.convert(max);
ElComparator elComparator = getElComparator(propertyName);
diff --git a/src/main/java/com/avaje/ebeaninternal/server/el/ElMatchBuilder.java b/src/main/java/com/avaje/ebeaninternal/server/el/ElMatchBuilder.java
index 4b0892196..343f8e904 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/el/ElMatchBuilder.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/el/ElMatchBuilder.java
@@ -28,7 +28,7 @@ class ElMatchBuilder {
}
public boolean isMatch(T bean) {
- String v = (String) elGetValue.elGetValue((EntityBean) bean);
+ String v = (String) elGetValue.pathGet(bean);
return pattern.matcher(v).matches();
}
}
@@ -55,7 +55,7 @@ class ElMatchBuilder {
}
public boolean isMatch(T bean) {
- String v = (String) elGetValue.elGetValue((EntityBean) bean);
+ String v = (String) elGetValue.pathGet(bean);
return value.equalsIgnoreCase(v);
}
}
@@ -75,7 +75,7 @@ class ElMatchBuilder {
public boolean isMatch(T bean) {
- String v = (String) elGetValue.elGetValue((EntityBean) bean);
+ String v = (String) elGetValue.pathGet(bean);
return charMatch.startsWith(v);
}
}
@@ -95,7 +95,7 @@ class ElMatchBuilder {
public boolean isMatch(T bean) {
- String v = (String) elGetValue.elGetValue((EntityBean) bean);
+ String v = (String) elGetValue.pathGet(bean);
return charMatch.endsWith(v);
}
}
@@ -106,7 +106,7 @@ class ElMatchBuilder {
}
public boolean isMatch(T bean) {
- String v = (String) elGetValue.elGetValue((EntityBean) bean);
+ String v = (String) elGetValue.pathGet(bean);
return value.startsWith(v);
}
}
@@ -117,7 +117,7 @@ class ElMatchBuilder {
}
public boolean isMatch(T bean) {
- String v = (String) elGetValue.elGetValue((EntityBean) bean);
+ String v = (String) elGetValue.pathGet(bean);
return value.endsWith(v);
}
}
@@ -131,7 +131,7 @@ class ElMatchBuilder {
}
public boolean isMatch(T bean) {
- return (null == elGetValue.elGetValue((EntityBean) bean));
+ return (null == elGetValue.pathGet(bean));
}
}
@@ -144,7 +144,7 @@ class ElMatchBuilder {
}
public boolean isMatch(T bean) {
- return (null != elGetValue.elGetValue((EntityBean) bean));
+ return (null != elGetValue.pathGet(bean));
}
}
@@ -175,7 +175,7 @@ class ElMatchBuilder {
public boolean isMatch(T bean) {
- Object value = elGetValue.elGetValue((EntityBean) bean);
+ Object value = elGetValue.pathGet(bean);
return value != null && set.contains(value);
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyChain.java b/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyChain.java
index 9f7214eaa..8c5817ff0 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyChain.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyChain.java
@@ -220,20 +220,19 @@ public class ElPropertyChain implements ElPropertyValue {
return scalarType;
}
- public Object elConvertType(Object value) {
+ public Object convert(Object value) {
// just convert using the last one in the chain
- return lastElPropertyValue.elConvertType(value);
+ return lastElPropertyValue.convert(value);
}
- public Object elGetValue(EntityBean bean) {
-
+ @Override
+ public Object pathGet(Object bean) {
for (int i = 0; i < chain.length; i++) {
- bean = (EntityBean) chain[i].elGetValue(bean);
+ bean = chain[i].pathGet(bean);
if (bean == null) {
return null;
}
}
-
return bean;
}
@@ -245,39 +244,25 @@ public class ElPropertyChain implements ElPropertyValue {
prevBean = (EntityBean) chain[i].elGetReference(prevBean);
}
// try the last step in the chain
- return chain[last].elGetValue(prevBean);
+ return chain[last].pathGet(prevBean);
}
@Override
- public void set(Object bean, Object value) {
- elSetValue((EntityBean)bean, value, true);
- }
+ public void pathSet(Object bean, Object value) {
- public void elSetValue(EntityBean bean, Object value, boolean populate) {
-
- EntityBean prevBean = bean;
- if (populate) {
- for (int i = 0; i < last; i++) {
- // always return non null prevBean
- prevBean = (EntityBean) chain[i].elGetReference(prevBean);
- }
- } else {
- for (int i = 0; i < last; i++) {
- // always return non null prevBean
- prevBean = (EntityBean) chain[i].elGetValue(prevBean);
- if (prevBean == null) {
- break;
- }
- }
+ EntityBean prevBean = (EntityBean)bean;
+ for (int i = 0; i < last; i++) {
+ // always return non null prevBean
+ prevBean = (EntityBean) chain[i].elGetReference(prevBean);
}
if (prevBean != null) {
if (lastBeanProperty != null) {
// last chain element maps to a real scalar property
- lastBeanProperty.setValueIntercept(prevBean, value);
+ lastBeanProperty.pathSet(prevBean, value);
} else {
// a non-scalar property of a Compound value object
- lastElPropertyValue.elSetValue(prevBean, value, populate);
+ lastElPropertyValue.pathSet(prevBean, value);
}
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyValue.java b/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyValue.java
index 8ba64b744..d48361efd 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyValue.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyValue.java
@@ -60,53 +60,10 @@ public interface ElPropertyValue extends ElPropertyDeploy, ExpressionPath {
*/
int getDeployOrder();
- /**
- * Return the default StringParser for the scalar property.
- */
- StringParser getStringParser();
-
- /**
- * Return true if the last type is "DateTime capable" - can support
- * {@link #parseDateTime(long)}.
- */
- boolean isDateTimeCapable();
-
- /**
- * Return the underlying JDBC type or 0 if this is not a scalar type.
- */
- int getJdbcType();
-
- /**
- * For DateTime capable scalar types convert the long systemTimeMillis into
- * an appropriate java time (Date,Timestamp,Time,Calendar, JODA type etc).
- */
- Object parseDateTime(long systemTimeMillis);
-
- /**
- * Return the value from a given entity bean.
- */
- Object elGetValue(EntityBean bean);
-
/**
* Return the value ensuring objects prior to the top scalar property are
* automatically populated.
*/
Object elGetReference(EntityBean bean);
- /**
- * Set a value given a root level bean.
- *
- * If populate then
- *
- */
- void elSetValue(EntityBean bean, Object value, boolean populate);
-
- /**
- * Convert the value to the expected type.
- *
- * Typically useful for converting strings to the appropriate number type
- * etc.
- *
- */
- Object elConvertType(Object value);
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPlanStats.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPlanStats.java
index 6196867ac..c1cd7ca85 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPlanStats.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPlanStats.java
@@ -230,7 +230,6 @@ public final class CQueryPlanStats {
return queryPlan.isAutoTuned();
}
-
@Override
public String getQueryPlanHash() {
return queryPlan.getPlanKey().toString();
diff --git a/src/main/java/com/avaje/ebeaninternal/server/text/csv/TCsvReader.java b/src/main/java/com/avaje/ebeaninternal/server/text/csv/TCsvReader.java
index 9cef2cb9a..ec98b1ed7 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/text/csv/TCsvReader.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/text/csv/TCsvReader.java
@@ -13,6 +13,7 @@ import java.util.Locale;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.bean.EntityBean;
+import com.avaje.ebean.plugin.ExpressionPath;
import com.avaje.ebean.text.StringParser;
import com.avaje.ebean.text.TextException;
import com.avaje.ebean.text.TimeStringParser;
@@ -24,8 +25,7 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
/**
- *
- * @author rbygrave
+ * Implementation of the CsvReader
*/
public class TCsvReader implements CsvReader {
@@ -55,9 +55,6 @@ public class TCsvReader implements CsvReader {
private boolean addPropertiesFromHeader;
- // private String addHeaderDateTimeFormat;
- // private Locale addHeaderLocale;
-
public TCsvReader(EbeanServer server, BeanDescriptor descriptor) {
this.server = server;
this.descriptor = descriptor;
@@ -114,11 +111,10 @@ public class TCsvReader implements CsvReader {
public void addDateTime(String propertyName, String dateTimeFormat, Locale locale) {
- ElPropertyValue elProp = descriptor.getElGetValue(propertyName);
+ ExpressionPath elProp = descriptor.getExpressionPath(propertyName);
if (!elProp.isDateTimeCapable()) {
throw new TextException("Property " + propertyName + " is not DateTime capable");
}
-
if (dateTimeFormat == null) {
dateTimeFormat = getDefaultDateTimeFormat(elProp.getJdbcType());
}
@@ -150,7 +146,7 @@ public class TCsvReader implements CsvReader {
public void addProperty(String propertyName, StringParser parser) {
- ElPropertyValue elProp = descriptor.getElGetValue(propertyName);
+ ExpressionPath elProp = descriptor.getExpressionPath(propertyName);
if (parser == null) {
parser = elProp.getStringParser();
}
@@ -214,7 +210,7 @@ public class TCsvReader implements CsvReader {
callback.end(row);
} catch (Exception e) {
- // notify that an error occured so that any
+ // notify that an error occurred so that any
// transaction can be rolled back if required
callback.endWithError(row, e);
throw e;
@@ -285,26 +281,23 @@ public class TCsvReader implements CsvReader {
*/
public static class CsvColumn {
- private final ElPropertyValue elProp;
+ private final ExpressionPath path;
private final StringParser parser;
- private final boolean ignore;
/**
* Constructor for the IGNORE column.
*/
private CsvColumn() {
- this.elProp = null;
+ this.path = null;
this.parser = null;
- this.ignore = true;
}
/**
* Construct with a property and parser.
*/
- public CsvColumn(ElPropertyValue elProp, StringParser parser) {
- this.elProp = elProp;
+ public CsvColumn(ExpressionPath path, StringParser parser) {
+ this.path = path;
this.parser = parser;
- this.ignore = false;
}
/**
@@ -312,9 +305,9 @@ public class TCsvReader implements CsvReader {
*/
public void convertAndSet(String strValue, EntityBean bean) {
- if (!ignore) {
+ if (parser != null && path != null) {
Object value = parser.parse(strValue);
- elProp.elSetValue(bean, value, true);
+ path.pathSet(bean, value);
}
}
}
@@ -327,19 +320,19 @@ public class TCsvReader implements CsvReader {
private static class DateTimeParser implements StringParser {
private final DateFormat dateFormat;
- private final ElPropertyValue elProp;
+ private final ExpressionPath path;
private final String format;
- DateTimeParser(DateFormat dateFormat, String format, ElPropertyValue elProp) {
+ DateTimeParser(DateFormat dateFormat, String format, ExpressionPath path) {
this.dateFormat = dateFormat;
- this.elProp = elProp;
+ this.path = path;
this.format = format;
}
public Object parse(String value) {
try {
Date dt = dateFormat.parse(value);
- return elProp.parseDateTime(dt.getTime());
+ return path.parseDateTime(dt.getTime());
} catch (ParseException e) {
throw new TextException("Error parsing [" + value + "] using format[" + format + "]", e);
diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/CtCompoundPropertyElAdapter.java b/src/main/java/com/avaje/ebeaninternal/server/type/CtCompoundPropertyElAdapter.java
index ef7255fdc..f7171beac 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/type/CtCompoundPropertyElAdapter.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/type/CtCompoundPropertyElAdapter.java
@@ -28,7 +28,8 @@ public class CtCompoundPropertyElAdapter implements ElPropertyValue {
this.deployOrder = deployOrder;
}
- public Object elConvertType(Object value) {
+ @Override
+ public Object convert(Object value) {
return value;
}
@@ -36,16 +37,13 @@ public class CtCompoundPropertyElAdapter implements ElPropertyValue {
return bean;
}
- public Object elGetValue(EntityBean bean) {
+ @Override
+ public Object pathGet(Object bean) {
return prop.getValue(bean);
}
@Override
- public void set(Object bean, Object value) {
- elSetValue((EntityBean) bean, value, true);
- }
-
- public void elSetValue(EntityBean bean, Object value, boolean populate) {
+ public void pathSet(Object bean, Object value) {
prop.setValue(bean, value);
}
diff --git a/src/main/java/com/avaje/ebeanservice/docstore/api/DocStoreBeanAdapter.java b/src/main/java/com/avaje/ebeanservice/docstore/api/DocStoreBeanAdapter.java
index 2e97058ab..73e1c3e6f 100644
--- a/src/main/java/com/avaje/ebeanservice/docstore/api/DocStoreBeanAdapter.java
+++ b/src/main/java/com/avaje/ebeanservice/docstore/api/DocStoreBeanAdapter.java
@@ -113,4 +113,9 @@ public interface DocStoreBeanAdapter extends BeanDocType {
*
*/
String rawProperty(String property);
+
+ /**
+ * Return true if this bean type as embedded invalidate registered.
+ */
+ boolean hasEmbeddedInvalidation();
}
diff --git a/src/main/java/com/avaje/ebeanservice/docstore/api/support/DocStoreBeanBaseAdapter.java b/src/main/java/com/avaje/ebeanservice/docstore/api/support/DocStoreBeanBaseAdapter.java
index 48de04387..168af4037 100644
--- a/src/main/java/com/avaje/ebeanservice/docstore/api/support/DocStoreBeanBaseAdapter.java
+++ b/src/main/java/com/avaje/ebeanservice/docstore/api/support/DocStoreBeanBaseAdapter.java
@@ -4,12 +4,15 @@ import com.avaje.ebean.FetchPath;
import com.avaje.ebean.Query;
import com.avaje.ebean.annotation.DocStore;
import com.avaje.ebean.annotation.DocStoreMode;
+import com.avaje.ebean.plugin.BeanType;
import com.avaje.ebean.text.PathProperties;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
+import com.avaje.ebeaninternal.server.deploy.InheritInfo;
+import com.avaje.ebeaninternal.server.deploy.InheritInfoVisitor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeanservice.docstore.api.DocStoreBeanAdapter;
import com.avaje.ebeanservice.docstore.api.DocStoreUpdateContext;
@@ -41,11 +44,6 @@ public abstract class DocStoreBeanBaseAdapter implements DocStoreBeanAdapter<
*/
protected final boolean mapped;
- /**
- * Nested path properties defining the doc structure for indexing.
- */
- protected final DocStructure docStructure;
-
/**
* Identifier used in the queue system to identify the index.
*/
@@ -87,18 +85,28 @@ public abstract class DocStoreBeanBaseAdapter implements DocStoreBeanAdapter<
*/
protected final List embeddedInvalidation = new ArrayList();
+ protected final PathProperties pathProps;
+
/**
* Map of properties to 'raw' properties.
*/
- private Map sortableMap;
+ protected Map sortableMap;
+ /**
+ * Nested path properties defining the doc structure for indexing.
+ */
+ protected DocStructure docStructure;
+
+ protected DocumentMapping documentMapping;
+
+ private boolean registerPaths;
public DocStoreBeanBaseAdapter(BeanDescriptor desc, DeployBeanDescriptor deploy) {
this.desc = desc;
this.server = desc.getEbeanServer();
this.mapped = deploy.isDocStoreMapped();
- this.docStructure = (!mapped) ? null : derivePathProperties(deploy);
+ this.pathProps = deploy.getDocStorePathProperties();
this.docStore = deploy.getDocStore();
this.queueId = derive(desc, deploy.getDocStoreQueueId());
this.indexName = derive(desc, deploy.getDocStoreIndexName());
@@ -108,28 +116,30 @@ public abstract class DocStoreBeanBaseAdapter implements DocStoreBeanAdapter<
this.delete = deploy.getDocStoreDeleteEvent();
}
+ @Override
+ public boolean hasEmbeddedInvalidation() {
+ return !embeddedInvalidation.isEmpty();
+ }
+
@Override
public DocumentMapping createDocMapping() {
+ if (documentMapping != null) {
+ return documentMapping;
+ }
+
if (!mapped) return null;
- PathProperties paths = docStructure.doc();
+ this.docStructure = derivePathProperties(pathProps);
- DocMappingBuilder mappingBuilder = new DocMappingBuilder(paths, docStore);
+ DocMappingBuilder mappingBuilder = new DocMappingBuilder(docStructure.doc(), docStore);
desc.docStoreMapping(mappingBuilder, null);
-
mappingBuilder.applyMapping();
- prepareMapping(mappingBuilder);
sortableMap = mappingBuilder.collectSortable();
-
docStructure.prepareMany(desc);
-
- return mappingBuilder.create(queueId, indexName, indexType);
- }
-
- protected void prepareMapping(DocMappingBuilder mappingBuilder) {
- // do nothing by default
+ documentMapping = mappingBuilder.create(queueId, indexName, indexType);
+ return documentMapping;
}
@Override
@@ -159,7 +169,7 @@ public abstract class DocStoreBeanBaseAdapter implements DocStoreBeanAdapter<
*/
@Override
public void registerPaths() {
- if (mapped) {
+ if (mapped && !registerPaths) {
Collection pathProps = docStructure.doc().getPathProps();
for (PathProperties.Props pathProp : pathProps) {
String path = pathProp.getPath();
@@ -170,6 +180,7 @@ public abstract class DocStoreBeanBaseAdapter implements DocStoreBeanAdapter<
targetDesc.docStoreAdapter().registerInvalidationPath(desc.getDocStoreQueueId(), fullPath, pathProp.getProperties());
}
}
+ registerPaths = true;
}
}
@@ -223,13 +234,8 @@ public abstract class DocStoreBeanBaseAdapter implements DocStoreBeanAdapter<
* Return the pathProperties which defines the JSON document to index.
* This can add derived/embedded/nested parts to the document.
*/
- protected DocStructure derivePathProperties(DeployBeanDescriptor deploy) {
+ protected DocStructure derivePathProperties(PathProperties pathProps) {
- if (!mapped) {
- return null;
- }
-
- PathProperties pathProps = deploy.getDocStorePathProperties();
boolean includeByDefault = (pathProps == null);
if (pathProps == null) {
pathProps = new PathProperties();
@@ -238,13 +244,27 @@ public abstract class DocStoreBeanBaseAdapter implements DocStoreBeanAdapter<
return getDocStructure(pathProps, includeByDefault);
}
- protected DocStructure getDocStructure(PathProperties pathProps, boolean includeByDefault) {
+ protected DocStructure getDocStructure(PathProperties pathProps, final boolean includeByDefault) {
+
+ final DocStructure docStructure = new DocStructure(pathProps);
- DocStructure docStructure = new DocStructure(pathProps);
BeanProperty[] properties = desc.propertiesNonTransient();
for (int i = 0; i < properties.length; i++) {
properties[i].docStoreInclude(includeByDefault, docStructure);
}
+
+ InheritInfo inheritInfo = desc.getInheritInfo();
+ if (inheritInfo != null) {
+ inheritInfo.visitChildren(new InheritInfoVisitor() {
+ @Override
+ public void visit(InheritInfo inheritInfo) {
+ for (BeanProperty localProperty : inheritInfo.localProperties()) {
+ localProperty.docStoreInclude(includeByDefault, docStructure);
+ }
+ }
+ });
+ }
+
return docStructure;
}
@@ -293,7 +313,7 @@ public abstract class DocStoreBeanBaseAdapter implements DocStoreBeanAdapter<
/**
* Return the supplied value or default to the bean name lower case.
*/
- protected String derive(BeanDescriptor desc, String suppliedValue) {
+ protected String derive(BeanType> desc, String suppliedValue) {
return (suppliedValue != null && suppliedValue.length() > 0) ? suppliedValue : desc.getName().toLowerCase();
}
diff --git a/src/main/java/com/avaje/ebeanservice/docstore/api/support/DocStructure.java b/src/main/java/com/avaje/ebeanservice/docstore/api/support/DocStructure.java
index 87a07a01b..adb658759 100644
--- a/src/main/java/com/avaje/ebeanservice/docstore/api/support/DocStructure.java
+++ b/src/main/java/com/avaje/ebeanservice/docstore/api/support/DocStructure.java
@@ -73,7 +73,7 @@ public class DocStructure {
public void prepareMany(BeanDescriptor desc) {
Set strings = embedded.keySet();
for (String prop : strings) {
- BeanPropertyAssoc> embProp = (BeanPropertyAssoc>)desc.getBeanProperty(prop);
+ BeanPropertyAssoc> embProp = (BeanPropertyAssoc>)desc.findBeanProperty(prop);
if (embProp.isMany()) {
prepare(prop, embProp);
}
diff --git a/src/test/java/com/avaje/ebean/plugin/BeanTypeTest.java b/src/test/java/com/avaje/ebean/plugin/BeanTypeTest.java
index 917d9653a..1ca3b45db 100644
--- a/src/test/java/com/avaje/ebean/plugin/BeanTypeTest.java
+++ b/src/test/java/com/avaje/ebean/plugin/BeanTypeTest.java
@@ -3,17 +3,24 @@ package com.avaje.ebean.plugin;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.FetchPath;
+import com.avaje.ebean.Query;
import com.avaje.ebean.text.PathProperties;
import com.avaje.ebeaninternal.api.SpiQuery;
import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail;
+import com.avaje.tests.inheritance.Stockforecast;
+import com.avaje.tests.model.basic.Car;
import com.avaje.tests.model.basic.Customer;
import com.avaje.tests.model.basic.Order;
import com.avaje.tests.model.basic.OrderDetail;
import com.avaje.tests.model.basic.Person;
import com.avaje.tests.model.basic.Product;
+import com.avaje.tests.model.basic.Vehicle;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
public class BeanTypeTest {
@@ -189,4 +196,48 @@ public class BeanTypeTest {
public void docStoreUpdateEmbedded() throws Exception {
beanType(Order.class).docStore().updateEmbedded(1, "customer", "someJson", null);
}
+
+ @Test
+ public void hasInheritance_when_not() {
+ assertFalse(beanType(Order.class).hasInheritance());
+ }
+
+ @Test
+ public void hasInheritance_when_root() {
+ assertTrue(beanType(Vehicle.class).hasInheritance());
+ }
+
+ @Test
+ public void hasInheritance_when_leaf() {
+ assertTrue(beanType(Car.class).hasInheritance());
+ }
+
+ @Test
+ public void getDiscColumn_when_default() {
+ assertEquals(beanType(Car.class).getDiscColumn(),"dtype");
+ }
+
+ @Test
+ public void getDiscColumn_when_set() {
+ assertEquals(beanType(Stockforecast.class).getDiscColumn(),"type");
+ }
+
+ @Test
+ public void createBeanUsingDisc_when_set() {
+ Vehicle vehicle = beanType(Vehicle.class).createBeanUsingDisc("C");
+ assertTrue(vehicle instanceof Car);
+ }
+
+ @Test
+ public void addInheritanceWhere_when_leaf() {
+ Query query = server.find(Vehicle.class);
+ beanType(Car.class).addInheritanceWhere((SpiQuery>)query);
+ }
+
+ @Test
+ public void addInheritanceWhere_when_root() {
+ Query query = server.find(Vehicle.class);
+ beanType(Vehicle.class).addInheritanceWhere((SpiQuery>)query);
+ }
+
}
\ No newline at end of file
diff --git a/src/test/java/com/avaje/ebean/plugin/ExpressionPathTest.java b/src/test/java/com/avaje/ebean/plugin/ExpressionPathTest.java
index 54ba6bd46..809e92200 100644
--- a/src/test/java/com/avaje/ebean/plugin/ExpressionPathTest.java
+++ b/src/test/java/com/avaje/ebean/plugin/ExpressionPathTest.java
@@ -63,7 +63,7 @@ public class ExpressionPathTest {
BeanType beanType = beanType(Order.class);
Order order = new Order();
- beanType.getExpressionPath("id").set(order, 42);
+ beanType.getExpressionPath("id").pathSet(order, 42);
assertThat(order.getId()).isEqualTo(42);
}
@@ -72,7 +72,7 @@ public class ExpressionPathTest {
BeanType beanType = beanType(Order.class);
Order order = new Order();
- beanType.getExpressionPath("customer.name").set(order, "Rob");
+ beanType.getExpressionPath("customer.name").pathSet(order, "Rob");
assertThat(order.getCustomer().getName()).isEqualTo("Rob");
}
diff --git a/src/test/java/com/avaje/tests/ddd/iud/TestDPersonEl.java b/src/test/java/com/avaje/tests/ddd/iud/TestDPersonEl.java
index 2f28f7d26..8f1157b4b 100644
--- a/src/test/java/com/avaje/tests/ddd/iud/TestDPersonEl.java
+++ b/src/test/java/com/avaje/tests/ddd/iud/TestDPersonEl.java
@@ -2,62 +2,67 @@ package com.avaje.tests.ddd.iud;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.bean.EntityBean;
+import com.avaje.ebean.plugin.BeanType;
+import com.avaje.ebean.plugin.ExpressionPath;
+import com.avaje.ebean.plugin.SpiServer;
import com.avaje.ebean.text.json.JsonContext;
-import com.avaje.ebeaninternal.api.SpiEbeanServer;
-import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
-import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.tests.model.ddd.DPerson;
import com.avaje.tests.model.ivo.CMoney;
import com.avaje.tests.model.ivo.Money;
-import junit.framework.TestCase;
-import org.junit.Assert;
+import org.junit.Test;
import java.io.IOException;
import java.util.Currency;
-public class TestDPersonEl extends TestCase {
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
- public void test() throws IOException {
+public class TestDPersonEl {
- Currency NZD = Currency.getInstance("NZD");
-
- DPerson p = new DPerson();
- p.setFirstName("first");
- p.setLastName("last");
- p.setSalary(new Money("12200"));
- p.setCmoney(new CMoney(new Money("12"), NZD));
-
- SpiEbeanServer server = (SpiEbeanServer)Ebean.getServer(null);
-
- BeanDescriptor descriptor = server.getBeanDescriptor(DPerson.class);
-
- ElPropertyValue elCmoney = descriptor.getElGetValue("cmoney");
-// ElPropertyValue elCmoneyAmt = descriptor.getElGetValue("cmoney.amount");
-// ElPropertyValue elCmoneyCur = descriptor.getElGetValue("cmoney.currency");
-
- JsonContext jsonContext = server.json();
- String json = jsonContext.toJson(p);
-
- DPerson bean = jsonContext.toBean(DPerson.class, json);
- Assert.assertEquals("first", bean.getFirstName());
- Assert.assertEquals(new Money("12200"), bean.getSalary());
- Assert.assertEquals(new Money("12"), bean.getCmoney().getAmount());
- Assert.assertEquals(NZD, bean.getCmoney().getCurrency());
-
-
- EntityBean entityBean = (EntityBean)p;
-
- Object cmoney = elCmoney.elGetValue(entityBean);
-// Object amt = elCmoneyAmt.elGetValue(entityBean);
-// Object cur = elCmoneyCur.elGetValue(entityBean);
-
- Assert.assertNotNull(cmoney);
-// Assert.assertEquals(new Money("12"), amt);
-// Assert.assertEquals(NZD, cur);
-
- p.setCmoney(null);
- Assert.assertNull(p.getCmoney());
+ @Test
+ public void test() throws IOException {
+
+ Currency NZD = Currency.getInstance("NZD");
+
+ DPerson p = new DPerson();
+ p.setFirstName("first");
+ p.setLastName("last");
+ p.setSalary(new Money("12200"));
+ p.setCmoney(new CMoney(new Money("12"), NZD));
+
+ SpiServer server = Ebean.getDefaultServer().getPluginApi();
+
+ BeanType descriptor = server.getBeanType(DPerson.class);
+
+
+ JsonContext jsonContext = server.json();
+ String json = jsonContext.toJson(p);
+
+ DPerson bean = jsonContext.toBean(DPerson.class, json);
+ assertEquals("first", bean.getFirstName());
+ assertEquals(new Money("12200"), bean.getSalary());
+ assertEquals(new Money("12"), bean.getCmoney().getAmount());
+ assertEquals(NZD, bean.getCmoney().getCurrency());
+
+
+ EntityBean entityBean = (EntityBean) p;
+
+ ExpressionPath elCmoney = descriptor.getExpressionPath("cmoney");
+ ExpressionPath elCmoneyAmt = descriptor.getExpressionPath("cmoney.amount");
+ ExpressionPath elCmoneyCur = descriptor.getExpressionPath("cmoney.currency");
+
+ Object cmoney = elCmoney.pathGet(entityBean);
+ Object amt = elCmoneyAmt.pathGet(entityBean);
+ Object cur = elCmoneyCur.pathGet(entityBean);
+
+ assertNotNull(cmoney);
+ assertEquals(new Money("12"), amt);
+ assertEquals(NZD, cur);
+
+ p.setCmoney(null);
+ assertNull(p.getCmoney());
+
+ }
- }
-
}
diff --git a/src/test/java/com/avaje/tests/el/TestElGetReference.java b/src/test/java/com/avaje/tests/el/TestElGetReference.java
deleted file mode 100644
index a6ecf5f02..000000000
--- a/src/test/java/com/avaje/tests/el/TestElGetReference.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.avaje.tests.el;
-
-import junit.framework.TestCase;
-
-import com.avaje.ebean.Ebean;
-import com.avaje.ebean.bean.EntityBean;
-import com.avaje.ebeaninternal.api.SpiEbeanServer;
-import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
-import com.avaje.ebeaninternal.server.el.ElPropertyValue;
-import com.avaje.tests.model.basic.Address;
-import com.avaje.tests.model.basic.Customer;
-
-public class TestElGetReference extends TestCase {
-
-
- public void test() {
-
- Address a = new Address();
- a.setId((short)12);
- a.setLine1("line1");
- a.setCity("Auckland");
-
- Customer c0 = new Customer();
- c0.setBillingAddress(a);
-
- Customer c1 = new Customer();
-
- SpiEbeanServer server = (SpiEbeanServer)Ebean.getServer(null);
- BeanDescriptor descriptor = server.getBeanDescriptor(Customer.class);
-
- ElPropertyValue elProp = descriptor.getElGetValue("billingAddress.id");
- ElPropertyValue addrLine1Prop = descriptor.getElGetValue("billingAddress.line1");
- ElPropertyValue addrCityProp = descriptor.getElGetValue("billingAddress.city");
-
- elProp.elGetReference((EntityBean)c0);
- elProp.elGetReference((EntityBean)c1);
-
- addrLine1Prop.elSetValue((EntityBean)c1, "12 someplace", true);
- addrCityProp.elSetValue((EntityBean)c1, "Auckland", true);
- }
-}
diff --git a/src/test/java/com/avaje/tests/el/TestPathExpression.java b/src/test/java/com/avaje/tests/el/TestPathExpression.java
new file mode 100644
index 000000000..c9526b0db
--- /dev/null
+++ b/src/test/java/com/avaje/tests/el/TestPathExpression.java
@@ -0,0 +1,81 @@
+package com.avaje.tests.el;
+
+import com.avaje.ebean.Ebean;
+import com.avaje.ebean.bean.EntityBean;
+import com.avaje.ebean.plugin.BeanType;
+import com.avaje.ebean.plugin.ExpressionPath;
+import com.avaje.ebean.plugin.SpiServer;
+import com.avaje.tests.model.basic.Address;
+import com.avaje.tests.model.basic.Country;
+import com.avaje.tests.model.basic.Customer;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestPathExpression {
+
+ final BeanType beanType;
+ final ExpressionPath billingId;
+ final ExpressionPath line1;
+ final ExpressionPath city;
+
+ public TestPathExpression() {
+ SpiServer server = Ebean.getDefaultServer().getPluginApi();
+ beanType = server.getBeanType(Customer.class);
+ billingId = beanType.getExpressionPath("billingAddress.id");
+ line1 = beanType.getExpressionPath("billingAddress.line1");
+ city = beanType.getExpressionPath("billingAddress.city");
+ }
+
+ @Test
+ public void pathSet() {
+
+ Customer c1 = new Customer();
+ line1.pathSet(c1, "12 someplace");
+ city.pathSet(c1, "Auckland");
+ billingId.pathSet(c1, 4);
+
+ beanType.getExpressionPath("id").pathSet(c1, 42L);
+ beanType.getExpressionPath("name").pathSet(c1, "jimmy");
+ beanType.getExpressionPath("status").pathSet(c1, "ACTIVE");
+ beanType.getExpressionPath("billingAddress.country.code").pathSet(c1, "NZ");
+ beanType.getExpressionPath("billingAddress.country.name").pathSet(c1, "New Zealand");
+
+
+ assertEquals(c1.getId(), Integer.valueOf(42));
+ assertEquals(c1.getName(), "jimmy");
+ assertEquals(c1.getStatus(), Customer.Status.ACTIVE);
+ assertEquals(c1.getBillingAddress().getLine1(), "12 someplace");
+ assertEquals(c1.getBillingAddress().getCity(), "Auckland");
+ assertEquals(c1.getBillingAddress().getId(), Short.valueOf("4"));
+
+ assertEquals(c1.getBillingAddress().getCountry().getCode(), "NZ");
+ assertEquals(c1.getBillingAddress().getCountry().getName(), "New Zealand");
+ }
+
+ @Test
+ public void pathGet() {
+
+ Address billingAddress = new Address();
+ billingAddress.setId((short)12);
+ billingAddress.setLine1("line1");
+ billingAddress.setCity("Auckland");
+
+ Country nz = new Country();
+ nz.setCode("NZ");
+ nz.setName("New Zealand");
+ billingAddress.setCountry(nz);
+
+ Customer c0 = new Customer();
+ c0.setBillingAddress(billingAddress);
+
+ EntityBean e0 = (EntityBean)c0;
+ assertEquals(line1.pathGet(e0), "line1");
+ assertEquals(city.pathGet(e0), "Auckland");
+ assertEquals(billingId.pathGet(e0), Short.valueOf("12"));
+
+
+ assertEquals(beanType.getExpressionPath("billingAddress.country.code").pathGet(e0), "NZ");
+ assertEquals(beanType.getExpressionPath("billingAddress.country.name").pathGet(e0), "New Zealand");
+ }
+}