package org.wamblee.persistence;
import java.io.Serializable;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
}
private static EntityAccessor analyse(Class aClass) {
- Accessor<Serializable> pk = AnnotationUtils.analyse(aClass, Id.class);
- Accessor<Integer> version = AnnotationUtils.analyse(aClass, Version.class);
- if (pk != null || version != null) {
+ List<Accessor> pkAccessors = AnnotationUtils.analyse(aClass, Id.class);
+ List<Accessor> versionAccessors = AnnotationUtils.analyse(aClass,
+ Version.class);
+ Accessor<Serializable> pk = null;
+ if ( pkAccessors.size() > 0 ) {
+ pk = pkAccessors.get(0);
+ }
+ Accessor<Integer> version = null;
+ if ( versionAccessors.size() > 0 ) {
+ version = versionAccessors.get(0);
+ }
+ if (pk != null|| version != null) {
return new EntityAccessor(pk, version);
}
return null;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.List;
/**
* Class to analyse.
* @param aAnnotation
* Annotation that must be present.
- * @return Accessor to use or null if the annotation is not present.
+ * @return List of accessors. Empty list is returned if no match is found.
*/
// TODO move generic analysis part to the reflection package.
- public static Accessor analyse(Class aClass,
+ public static List<Accessor> analyse(Class aClass,
Class<? extends Annotation> aAnnotation) {
+ List<Accessor> result = new ArrayList<Accessor>();
+
List<Field> fields = ReflectionUtils.getAllFields(aClass);
for (Field field : fields) {
if (field.isAnnotationPresent(aAnnotation)) {
- return new FieldAccessor(field);
+ result.add(new FieldAccessor(field));
}
}
List<Method> methods = ReflectionUtils.getAllMethods(aClass,
Class returnType = method.getReturnType();
Method setter = method.getDeclaringClass()
.getDeclaredMethod(setterName, returnType);
- return new PropertyAccessor(method, setter);
+ result.add(new PropertyAccessor(method, setter));
} catch (NoSuchMethodException e) {
throw new RuntimeException("Error obtaining setter for " +
method.getName() + " in class " + aClass.getName(), e);
}
}
}
- return null;
+ return result;
}
}
--- /dev/null
+/*
+ * Copyright 2005-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wamblee.reflection;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.List;
+
+import org.junit.Test;
+
+import static junit.framework.TestCase.*;
+
+public class AnnotationUtilsTest {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.FIELD, ElementType.METHOD})
+ public static @interface MyAnnotation {
+
+ }
+
+ public static class X1 {
+ @MyAnnotation
+ public int x;
+ }
+
+ public static class X2 {
+ @MyAnnotation
+ private int x;
+
+ }
+
+ public static class X3 {
+ private int x;
+
+ public void setX(int aX) {
+ x = aX;
+ }
+
+ @MyAnnotation
+ public int getX() {
+ return x;
+ }
+ }
+
+ public static class X4 {
+ private int x;
+
+ private void setX(int aX) {
+ x = aX;
+ }
+
+ @MyAnnotation
+ private int getX() {
+ return x;
+ }
+ }
+
+ public static class X5 {
+ private int x;
+
+ @MyAnnotation
+ private int y;
+
+ private void setX(int aX) {
+ x = aX;
+ }
+
+ @MyAnnotation
+ private int getX() {
+ return x;
+ }
+ }
+
+
+
+ @Test
+ public void testPublicField() {
+ List<Accessor> accessors = AnnotationUtils.analyse(X1.class, MyAnnotation.class);
+ assertEquals(1, accessors.size());
+ assertTrue(accessors.get(0) instanceof FieldAccessor);
+
+ X1 obj = new X1();
+ assertEquals(0, obj.x);
+ accessors.get(0).set(obj, 100);
+ assertEquals(100,obj.x);
+ }
+
+ @Test
+ public void testPrivateField() {
+ List<Accessor> accessors = AnnotationUtils.analyse(X2.class, MyAnnotation.class);
+ assertEquals(1, accessors.size());
+ assertTrue(accessors.get(0) instanceof FieldAccessor);
+ X2 obj = new X2();
+ assertEquals(0, obj.x);
+ accessors.get(0).set(obj, 100);
+ assertEquals(100, obj.x);
+ }
+
+ @Test
+ public void testPublicProperty() {
+ List<Accessor> accessors = AnnotationUtils.analyse(X3.class, MyAnnotation.class);
+ assertEquals(1, accessors.size());
+ assertTrue(accessors.get(0) instanceof PropertyAccessor);
+ X3 obj = new X3();
+ assertEquals(0, obj.x);
+ accessors.get(0).set(obj, 100);
+ assertEquals(100, obj.x);
+ }
+
+ @Test
+ public void testPrivateProperty() {
+ List<Accessor> accessors = AnnotationUtils.analyse(X4.class, MyAnnotation.class);
+ assertEquals(1, accessors.size());
+ assertTrue(accessors.get(0) instanceof PropertyAccessor);
+ X4 obj = new X4();
+ assertEquals(0, obj.x);
+ accessors.get(0).set(obj, 100);
+ assertEquals(100, obj.x);
+ }
+
+ @Test
+ public void testMultipleMatches() {
+ List<Accessor> accessors = AnnotationUtils.analyse(X5.class, MyAnnotation.class);
+ assertEquals(2, accessors.size());
+ X5 obj = new X5();
+ assertEquals(0, obj.x);
+ assertEquals(0, obj.y);
+ for (Accessor accessor: accessors) {
+ accessor.set(obj, 100);
+ }
+ assertEquals(100, obj.x);
+ assertEquals(100, obj.y);
+ }
+}