You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by jo...@apache.org on 2013/10/14 19:36:24 UTC
svn commit: r1531989 - in
/cayenne/main/trunk/framework/cayenne-core-unpublished/src:
main/java/org/apache/cayenne/exp/ main/java/org/apache/cayenne/reflect/
test/java/org/apache/cayenne/exp/ test/java/org/apache/cayenne/reflect/
Author: johnthuss
Date: Mon Oct 14 17:36:24 2013
New Revision: 1531989
URL: http://svn.apache.org/r1531989
Log:
Add getFrom and setIn methods to Property for accessing object state via reflection; Implement equals and hashCode
Tweak the behavior of PropertyUtils.setProperty to match the behavior of PropertyUtils.getProperty when
nulls are encountered along a nested path - now the exception behavior is symmetric.
Modified:
cayenne/main/trunk/framework/cayenne-core-unpublished/src/main/java/org/apache/cayenne/exp/Property.java
cayenne/main/trunk/framework/cayenne-core-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java
cayenne/main/trunk/framework/cayenne-core-unpublished/src/test/java/org/apache/cayenne/exp/PropertyTest.java
cayenne/main/trunk/framework/cayenne-core-unpublished/src/test/java/org/apache/cayenne/reflect/TestJavaBean.java
Modified: cayenne/main/trunk/framework/cayenne-core-unpublished/src/main/java/org/apache/cayenne/exp/Property.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-core-unpublished/src/main/java/org/apache/cayenne/exp/Property.java?rev=1531989&r1=1531988&r2=1531989&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-core-unpublished/src/main/java/org/apache/cayenne/exp/Property.java (original)
+++ cayenne/main/trunk/framework/cayenne-core-unpublished/src/main/java/org/apache/cayenne/exp/Property.java Mon Oct 14 17:36:24 2013
@@ -26,6 +26,7 @@ import org.apache.cayenne.exp.parser.AST
import org.apache.cayenne.query.Ordering;
import org.apache.cayenne.query.PrefetchTreeNode;
import org.apache.cayenne.query.SortOrder;
+import org.apache.cayenne.reflect.PropertyUtils;
/**
* <p>
@@ -65,6 +66,16 @@ public class Property<E> {
public String getName() {
return name;
}
+
+ @Override
+ public int hashCode() {
+ return getName().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof Property && ((Property<?>)obj).getName().equals(getName());
+ }
/**
* @return Constructs a property path by appending the argument to the
@@ -377,4 +388,43 @@ public class Property<E> {
return node;
}
+ /**
+ * Extracts property value from an object using JavaBean-compatible introspection with one addition -
+ * a property can be a dot-separated property name path.
+ */
+ @SuppressWarnings("unchecked")
+ public E getFrom(Object bean) {
+ return (E)PropertyUtils.getProperty(bean, getName());
+ }
+
+ /**
+ * Extracts property value from a collection of objects using JavaBean-compatible introspection with one addition -
+ * a property can be a dot-separated property name path.
+ */
+ public List<E> getFromAll(Collection<?> beans) {
+ List<E> result = new ArrayList<E>(beans.size());
+ for (Object bean : beans) {
+ result.add(getFrom(bean));
+ }
+ return result;
+ }
+
+ /**
+ * Sets a property value in 'obj' using JavaBean-compatible introspection with one addition -
+ * a property can be a dot-separated property name path.
+ */
+ public void setIn(Object bean, E value) {
+ PropertyUtils.setProperty(bean, getName(), value);
+ }
+
+ /**
+ * Sets a property value in a collection of objects using JavaBean-compatible introspection with one addition -
+ * a property can be a dot-separated property name path.
+ */
+ public void setInAll(Collection<?> beans, E value) {
+ for (Object bean : beans) {
+ setIn(bean, value);
+ }
+ }
+
}
\ No newline at end of file
Modified: cayenne/main/trunk/framework/cayenne-core-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-core-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java?rev=1531989&r1=1531988&r2=1531989&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-core-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java (original)
+++ cayenne/main/trunk/framework/cayenne-core-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java Mon Oct 14 17:36:24 2013
@@ -151,11 +151,16 @@ public class PropertyUtils {
if (dot > 0) {
lastSegment = nestedPropertyName.substring(dot + 1);
String pathSegment = nestedPropertyName.substring(0, dot);
- object = getProperty(object, pathSegment);
+ Object intermediateObject = getProperty(object, pathSegment);
- if (object == null) {
- throw new IllegalArgumentException(
- "Null object at the end of the segment '" + pathSegment + "'");
+ if (intermediateObject == null) {
+ throw new UnresolvablePathException(
+ "Null value in the middle of the path, failed on "
+ + pathSegment
+ + " from "
+ + object);
+ } else {
+ object = intermediateObject;
}
}
else {
Modified: cayenne/main/trunk/framework/cayenne-core-unpublished/src/test/java/org/apache/cayenne/exp/PropertyTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-core-unpublished/src/test/java/org/apache/cayenne/exp/PropertyTest.java?rev=1531989&r1=1531988&r2=1531989&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-core-unpublished/src/test/java/org/apache/cayenne/exp/PropertyTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-core-unpublished/src/test/java/org/apache/cayenne/exp/PropertyTest.java Mon Oct 14 17:36:24 2013
@@ -19,9 +19,14 @@
package org.apache.cayenne.exp;
import java.util.Arrays;
+import java.util.List;
import junit.framework.TestCase;
+import org.apache.cayenne.reflect.TestJavaBean;
+import org.apache.cayenne.reflect.UnresolvablePathException;
+import org.apache.cayenne.util.Util;
+
public class PropertyTest extends TestCase {
public void testIn() {
@@ -36,4 +41,109 @@ public class PropertyTest extends TestCa
Expression e3 = p.in(Arrays.asList("a", "b"));
assertEquals("x.y in (\"a\", \"b\")", e3.toString());
}
+
+ public void testGetFrom() {
+ TestJavaBean bean = new TestJavaBean();
+ bean.setIntField(7);
+ final Property<Integer> INT_FIELD = new Property<Integer>("intField");
+ assertEquals(Integer.valueOf(7), INT_FIELD.getFrom(bean));
+ }
+
+ public void testGetFromNestedProperty() {
+ TestJavaBean bean = new TestJavaBean();
+ TestJavaBean nestedBean = new TestJavaBean();
+ nestedBean.setIntField(7);
+ bean.setObjectField(nestedBean);
+ final Property<Integer> OBJECT_FIELD_INT_FIELD = new Property<Integer>("objectField.intField");
+ assertEquals(Integer.valueOf(7), OBJECT_FIELD_INT_FIELD.getFrom(bean));
+ }
+
+ public void testGetFromNestedNull() {
+ TestJavaBean bean = new TestJavaBean();
+ bean.setObjectField(null);
+ final Property<Integer> OBJECT_FIELD_INT_FIELD = new Property<Integer>("objectField.intField");
+ try {
+ OBJECT_FIELD_INT_FIELD.getFrom(bean);
+ fail();
+ } catch (Exception e) {
+ Throwable rootException = Util.unwindException(e);
+ if (!(rootException instanceof UnresolvablePathException)) {
+ fail();
+ }
+ }
+ }
+
+ public void testGetFromAll() {
+ TestJavaBean bean = new TestJavaBean();
+ bean.setIntField(7);
+
+ TestJavaBean bean2 = new TestJavaBean();
+ bean2.setIntField(8);
+
+ List<TestJavaBean> beans = Arrays.asList(bean, bean2);
+
+ final Property<Integer> INT_FIELD = new Property<Integer>("intField");
+ assertEquals(Arrays.asList(7, 8), INT_FIELD.getFromAll(beans));
+ }
+
+ public void testSetIn() {
+ TestJavaBean bean = new TestJavaBean();
+ final Property<Integer> INT_FIELD = new Property<Integer>("intField");
+ INT_FIELD.setIn(bean, 7);
+ assertEquals(7, bean.getIntField());
+ }
+
+ public void testSetInNestedProperty() {
+ TestJavaBean bean = new TestJavaBean();
+ bean.setObjectField(new TestJavaBean());
+
+ final Property<Integer> OBJECT_FIELD_INT_FIELD = new Property<Integer>("objectField.intField");
+
+ OBJECT_FIELD_INT_FIELD.setIn(bean, 7);
+ assertEquals(7, ((TestJavaBean)bean.getObjectField()).getIntField());
+ }
+
+ public void testSetInNestedNull() {
+ TestJavaBean bean = new TestJavaBean();
+ bean.setObjectField(null);
+ final Property<Integer> OBJECT_FIELD_INT_FIELD = new Property<Integer>("objectField.intField");
+ try {
+ OBJECT_FIELD_INT_FIELD.setIn(bean, 7);
+ fail();
+ } catch (Exception e) {
+ Throwable rootException = Util.unwindException(e);
+ if (!(rootException instanceof UnresolvablePathException)) {
+ fail();
+ }
+ }
+ }
+
+ public void testSetInAll() {
+ TestJavaBean bean = new TestJavaBean();
+ TestJavaBean bean2 = new TestJavaBean();
+ List<TestJavaBean> beans = Arrays.asList(bean, bean2);
+
+ final Property<Integer> INT_FIELD = new Property<Integer>("intField");
+ INT_FIELD.setInAll(beans, 7);
+ assertEquals(7, bean.getIntField());
+ assertEquals(7, bean2.getIntField());
+ }
+
+ public void testEquals() {
+ final Property<Integer> INT_FIELD = new Property<Integer>("intField");
+ final Property<Integer> INT_FIELD2 = new Property<Integer>("intField");
+
+ assertTrue(INT_FIELD != INT_FIELD2);
+ assertTrue(INT_FIELD.equals(INT_FIELD2));
+ }
+
+ public void testHashCode() {
+ final Property<Integer> INT_FIELD = new Property<Integer>("intField");
+ final Property<Integer> INT_FIELD2 = new Property<Integer>("intField");
+ final Property<Long> LONG_FIELD = new Property<Long>("longField");
+
+ assertTrue(INT_FIELD.hashCode() == INT_FIELD2.hashCode());
+ assertTrue(INT_FIELD.hashCode() != LONG_FIELD.hashCode());
+ }
+
}
Modified: cayenne/main/trunk/framework/cayenne-core-unpublished/src/test/java/org/apache/cayenne/reflect/TestJavaBean.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-core-unpublished/src/test/java/org/apache/cayenne/reflect/TestJavaBean.java?rev=1531989&r1=1531988&r2=1531989&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-core-unpublished/src/test/java/org/apache/cayenne/reflect/TestJavaBean.java (original)
+++ cayenne/main/trunk/framework/cayenne-core-unpublished/src/test/java/org/apache/cayenne/reflect/TestJavaBean.java Mon Oct 14 17:36:24 2013
@@ -22,6 +22,8 @@ package org.apache.cayenne.reflect;
import java.sql.Timestamp;
import java.util.Date;
+import org.apache.cayenne.util.ToStringBuilder;
+
public class TestJavaBean extends Object {
protected String stringField;
@@ -172,4 +174,12 @@ public class TestJavaBean extends Object
public void setDoubleField(double doubleField) {
this.doubleField = doubleField;
}
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("intField", getIntField())
+ .append("objectField", getObjectField())
+ .toString();
+ }
}