You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xbean-scm@geronimo.apache.org by ga...@apache.org on 2009/04/30 21:46:48 UTC
svn commit: r770412 - in /geronimo/xbean/trunk/xbean-reflect/src:
main/java/org/apache/xbean/recipe/ObjectRecipe.java
main/java/org/apache/xbean/recipe/ReflectionUtil.java
test/java/org/apache/xbean/recipe/ObjectRecipeTest.java
Author: gawor
Date: Thu Apr 30 19:46:48 2009
New Revision: 770412
URL: http://svn.apache.org/viewvc?rev=770412&view=rev
Log:
basic support for compound properties
Modified:
geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java
geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java
geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/ObjectRecipeTest.java
Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java?rev=770412&r1=770411&r2=770412&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java Thu Apr 30 19:46:48 2009
@@ -194,6 +194,10 @@
setProperty(new AutoMatchProperty(type), value);
}
+ public void setCompoundProperty(String name, Object value) {
+ setProperty(new CompoundProperty(name), value);
+ }
+
private void setProperty(Property key, Object value) {
if (value instanceof UnsetPropertiesRecipe) {
allow(Option.IGNORE_MISSING_PROPERTIES);
@@ -424,6 +428,33 @@
throw new MissingAccessorException("Property of type " + propertyValue.getClass().getName() + " can be mapped to more then one setter: " + matches, 0);
}
}
+ } else if (propertyName instanceof CompoundProperty) {
+ String[] names = propertyName.name.split("\\.");
+ for (int i = 0; i < names.length - 1; i++) {
+ Method getter = ReflectionUtil.findGetter(clazz, names[i], options);
+ if (getter != null) {
+ try {
+ instance = getter.invoke(instance);
+ clazz = instance.getClass();
+ } catch (Exception e) {
+ Throwable t = e;
+ if (e instanceof InvocationTargetException) {
+ InvocationTargetException invocationTargetException = (InvocationTargetException) e;
+ if (invocationTargetException.getCause() != null) {
+ t = invocationTargetException.getCause();
+ }
+ }
+ throw new ConstructionException("Error setting property: " + names[i], t);
+ }
+ } else {
+ throw new ConstructionException("No getter for " + names[i] + " property");
+ }
+ }
+ List<Method> setters = ReflectionUtil.findAllSetters(clazz, names[names.length - 1], propertyValue, options);
+ for (Method setter : setters) {
+ MethodMember member = new MethodMember(setter);
+ members.add(member);
+ }
} else {
// add setter members
MissingAccessorException noSetter = null;
@@ -703,4 +734,17 @@
return "[auto-match] "+ super.toString();
}
}
+
+ public static class CompoundProperty extends Property {
+ public CompoundProperty(String type) {
+ super(type);
+ }
+
+ public int hashCode() {
+ return super.hashCode()+1;
+ }
+ public String toString() {
+ return "[compound] "+ super.toString();
+ }
+ }
}
Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java?rev=770412&r1=770411&r2=770412&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java Thu Apr 30 19:46:48 2009
@@ -150,6 +150,72 @@
}
}
+ public static Method findGetter(Class typeClass, String propertyName, Set<Option> options) {
+ if (typeClass == null) throw new NullPointerException("typeClass is null");
+ if (propertyName == null) throw new NullPointerException("name is null");
+ if (propertyName.length() == 0) throw new IllegalArgumentException("name is an empty string");
+ if (options == null) options = EnumSet.noneOf(Option.class);
+
+ if (propertyName.contains("/")){
+ String[] strings = propertyName.split("/");
+ if (strings == null || strings.length != 2) throw new IllegalArgumentException("badly formed <class>/<attribute> property name: " + propertyName);
+
+ String className = strings[0];
+ propertyName = strings[1];
+
+ boolean found = false;
+ while(!typeClass.equals(Object.class) && !found){
+ if (typeClass.getName().equals(className)){
+ found = true;
+ break;
+ } else {
+ typeClass = typeClass.getSuperclass();
+ }
+ }
+
+ if (!found) throw new MissingAccessorException("Type not assignable to class: " + className, -1);
+ }
+
+ String getterName = "get" + Character.toUpperCase(propertyName.charAt(0));
+ if (propertyName.length() > 0) {
+ getterName += propertyName.substring(1);
+ }
+
+ boolean allowPrivate = options.contains(Option.PRIVATE_PROPERTIES);
+ boolean allowStatic = options.contains(Option.STATIC_PROPERTIES);
+ boolean caseInsesnitive = options.contains(Option.CASE_INSENSITIVE_PROPERTIES);
+
+ List<Method> methods = new ArrayList<Method>(Arrays.asList(typeClass.getMethods()));
+ methods.addAll(Arrays.asList(typeClass.getDeclaredMethods()));
+ for (Method method : methods) {
+ if (method.getName().equals(getterName) || (caseInsesnitive && method.getName().equalsIgnoreCase(getterName))) {
+ if (method.getParameterTypes().length > 0) {
+ continue;
+ }
+ if (method.getReturnType() == Void.TYPE) {
+ continue;
+ }
+ if (Modifier.isAbstract(method.getModifiers())) {
+ continue;
+ }
+ if (!allowPrivate && !Modifier.isPublic(method.getModifiers())) {
+ continue;
+ }
+ if (!allowStatic && Modifier.isStatic(method.getModifiers())) {
+ continue;
+ }
+
+ if (allowPrivate && !Modifier.isPublic(method.getModifiers())) {
+ setAccessible(method);
+ }
+
+ return method;
+ }
+ }
+
+ return null;
+ }
+
public static Method findSetter(Class typeClass, String propertyName, Object propertyValue, Set<Option> options) {
List<Method> setters = findAllSetters(typeClass, propertyName, propertyValue, options);
return setters.get(0);
Modified: geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/ObjectRecipeTest.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/ObjectRecipeTest.java?rev=770412&r1=770411&r2=770412&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/ObjectRecipeTest.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/ObjectRecipeTest.java Thu Apr 30 19:46:48 2009
@@ -127,4 +127,58 @@
assertEquals(expectedConstruction, actual.getConstructionCalled());
}
+ public void testCompoundProperties() throws Exception {
+ ObjectRecipe objectRecipe = new ObjectRecipe(Component.class);
+ objectRecipe.setCompoundProperty("name", "Adam");
+ objectRecipe.setCompoundProperty("box.height", 5);
+ objectRecipe.setCompoundProperty("box.width", 10);
+
+ objectRecipe.setCompoundProperty("component.name", "Eva");
+ objectRecipe.setCompoundProperty("component.box.height", 10);
+ objectRecipe.setCompoundProperty("component.box.width", 20);
+
+ Component component = (Component) objectRecipe.create(Component.class.getClassLoader());
+
+ assertEquals("Adam", component.getName());
+ assertEquals(5, component.getBox().getHeight());
+ assertEquals(10, component.getBox().getWidth());
+
+ assertEquals("Eva", component.getComponent().getName());
+ assertEquals(10, component.getComponent().getBox().getHeight());
+ assertEquals(20, component.getComponent().getBox().getWidth());
+ }
+
+ public static class Component {
+
+ String name;
+ Box box;
+ Component component;
+
+ public Box getBox() {
+ if (box == null) {
+ box = new Box();
+ }
+ return box;
+ }
+
+ public Component getComponent() {
+ if (component == null) {
+ component = new Component();
+ }
+ return component;
+ }
+
+ public Component getNullComponent() {
+ return null;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ }
}