1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.joda.beans.impl.direct;
17
18 import java.lang.annotation.Annotation;
19 import java.lang.reflect.Field;
20 import java.lang.reflect.Type;
21 import java.util.Arrays;
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.NoSuchElementException;
25
26 import org.joda.beans.Bean;
27 import org.joda.beans.MetaBean;
28 import org.joda.beans.PropertyReadWrite;
29 import org.joda.beans.impl.BasicMetaProperty;
30
31
32
33
34
35
36
37
38
39 public final class DirectMetaProperty<P> extends BasicMetaProperty<P> {
40
41
42 private final MetaBean metaBean;
43
44 private final Class<P> propertyType;
45
46 private final Class<?> declaringType;
47
48 private final Field field;
49
50 private final PropertyReadWrite readWrite;
51
52
53
54
55
56
57
58
59
60
61
62 public static <P> DirectMetaProperty<P> ofReadWrite(
63 MetaBean metaBean, String propertyName, Class<?> declaringType, Class<P> propertyType) {
64 Field field = findField(metaBean, propertyName);
65 return new DirectMetaProperty<P>(metaBean, propertyName, declaringType, propertyType, PropertyReadWrite.READ_WRITE, field);
66 }
67
68
69
70
71
72
73
74
75
76
77
78 public static <P> DirectMetaProperty<P> ofReadOnly(
79 MetaBean metaBean, String propertyName, Class<?> declaringType, Class<P> propertyType) {
80 Field field = findField(metaBean, propertyName);
81 return new DirectMetaProperty<P>(metaBean, propertyName, declaringType, propertyType, PropertyReadWrite.READ_ONLY, field);
82 }
83
84
85
86
87
88
89
90
91
92
93
94 public static <P> DirectMetaProperty<P> ofWriteOnly(
95 MetaBean metaBean, String propertyName, Class<?> declaringType, Class<P> propertyType) {
96 Field field = findField(metaBean, propertyName);
97 return new DirectMetaProperty<P>(metaBean, propertyName, declaringType, propertyType, PropertyReadWrite.WRITE_ONLY, field);
98 }
99
100 private static Field findField(MetaBean metaBean, String propertyName) {
101 Field field = null;
102 Class<?> cls = metaBean.beanType();
103 while (cls != DirectBean.class) {
104 try {
105 field = cls.getDeclaredField(propertyName);
106 break;
107 } catch (NoSuchFieldException ex) {
108 try {
109 field = cls.getDeclaredField("_" + propertyName);
110 break;
111 } catch (NoSuchFieldException ex2) {
112 cls = cls.getSuperclass();
113 }
114 }
115 }
116 return field;
117 }
118
119
120
121
122
123
124
125
126
127
128
129 private DirectMetaProperty(MetaBean metaBean, String propertyName, Class<?> declaringType,
130 Class<P> propertyType, PropertyReadWrite readWrite, Field field) {
131 super(propertyName);
132 if (metaBean == null) {
133 throw new NullPointerException("MetaBean must not be null");
134 }
135 if (declaringType == null) {
136 throw new NullPointerException("Declaring type must not be null");
137 }
138 if (propertyType == null) {
139 throw new NullPointerException("Property type must not be null");
140 }
141 if (readWrite == null) {
142 throw new NullPointerException("PropertyReadWrite must not be null");
143 }
144 this.metaBean = metaBean;
145 this.propertyType = propertyType;
146 this.declaringType = declaringType;
147 this.readWrite = readWrite;
148 this.field = field;
149 }
150
151
152 @Override
153 public MetaBean metaBean() {
154 return metaBean;
155 }
156
157 @Override
158 public Class<?> declaringType() {
159 return declaringType;
160 }
161
162 @Override
163 public Class<P> propertyType() {
164 return propertyType;
165 }
166
167 @Override
168 public Type propertyGenericType() {
169 if (field == null) {
170 return propertyType;
171 }
172 return field.getGenericType();
173 }
174
175 @Override
176 public PropertyReadWrite readWrite() {
177 return readWrite;
178 }
179
180 @Override
181 public <A extends Annotation> A annotation(Class<A> annotationClass) {
182 if (field == null) {
183 throw new UnsupportedOperationException("Field not found for property: " + name());
184 }
185 A annotation = field.getAnnotation(annotationClass);
186 if (annotation == null) {
187 throw new NoSuchElementException("Unknown annotation: " + annotationClass.getName());
188 }
189 return annotation;
190 }
191
192 @Override
193 public List<Annotation> annotations() {
194 if (field == null) {
195 return Collections.emptyList();
196 }
197 return Arrays.asList(field.getDeclaredAnnotations());
198 }
199
200
201 @SuppressWarnings("unchecked")
202 @Override
203 public P get(Bean bean) {
204 return (P) ((DirectBean) bean).propertyGet(name(), false);
205 }
206
207 @Override
208 public void set(Bean bean, Object value) {
209 ((DirectBean) bean).propertySet(name(), value, false);
210 }
211
212 }