|
35 | 35 | import de.danielbechler.diff.selector.BeanPropertyElementSelector; |
36 | 36 | import de.danielbechler.util.Assert; |
37 | 37 |
|
38 | | -public class PropertyAccessor implements PropertyAwareAccessor |
39 | | -{ |
40 | | - private static final Logger logger = LoggerFactory.getLogger(PropertyAccessor.class); |
| 38 | +public class PropertyAccessor implements PropertyAwareAccessor { |
| 39 | + private static final Logger logger = LoggerFactory.getLogger(PropertyAccessor.class); |
41 | 40 |
|
42 | | - private final String propertyName; |
43 | | - private final Class<?> type; |
44 | | - private final Method readMethod; |
45 | | - private final Method writeMethod; |
| 41 | + private final String propertyName; |
| 42 | + private final Class<?> type; |
| 43 | + private final Method readMethod; |
| 44 | + private final Method writeMethod; |
46 | 45 | private final Field field; |
47 | 46 |
|
48 | | - public PropertyAccessor(final String propertyName, final Field f, final Method readMethod, final Method writeMethod) |
49 | | - { |
50 | | - Assert.notNull(propertyName, "propertyName"); |
51 | | - Assert.notNull(readMethod, "readMethod"); |
52 | | - this.propertyName = propertyName; |
| 47 | + public PropertyAccessor(final String propertyName, final Field f, final Method readMethod, final Method writeMethod) { |
| 48 | + Assert.notNull(propertyName, "propertyName"); |
| 49 | + Assert.notNull(readMethod, "readMethod"); |
| 50 | + this.propertyName = propertyName; |
53 | 51 | this.field = f; |
54 | | - this.readMethod = makeAccessible(readMethod); |
55 | | - this.writeMethod = makeAccessible(writeMethod); |
56 | | - this.type = this.readMethod.getReturnType(); |
57 | | - } |
| 52 | + this.readMethod = makeAccessible(readMethod); |
| 53 | + this.writeMethod = makeAccessible(writeMethod); |
| 54 | + this.type = this.readMethod.getReturnType(); |
| 55 | + } |
58 | 56 |
|
59 | | - private static Method makeAccessible(final Method method) |
60 | | - { |
61 | | - if (method != null && !method.isAccessible()) |
62 | | - { |
63 | | - logger.debug("Making method accessible: {}", method.toString()); |
64 | | - method.setAccessible(true); |
65 | | - } |
66 | | - return method; |
67 | | - } |
| 57 | + private static Method makeAccessible(final Method method) { |
| 58 | + if (method != null && !method.isAccessible()) { |
| 59 | + logger.debug("Making method accessible: {}", method.toString()); |
| 60 | + method.setAccessible(true); |
| 61 | + } |
| 62 | + return method; |
| 63 | + } |
68 | 64 |
|
69 | | - public final Set<String> getCategoriesFromAnnotation() |
70 | | - { |
71 | | - final ObjectDiffProperty annotation = readMethod.getAnnotation(ObjectDiffProperty.class); |
72 | | - if (annotation != null) |
73 | | - { |
74 | | - return new TreeSet<String>(asList(annotation.categories())); |
75 | | - } |
76 | | - return Collections.emptySet(); |
77 | | - } |
| 65 | + public final Set<String> getCategoriesFromAnnotation() { |
| 66 | + final ObjectDiffProperty annotation = readMethod.getAnnotation(ObjectDiffProperty.class); |
| 67 | + if (annotation != null) { |
| 68 | + return new TreeSet<String>(asList(annotation.categories())); |
| 69 | + } |
| 70 | + return Collections.emptySet(); |
| 71 | + } |
78 | 72 |
|
79 | | - public boolean isExcludedByAnnotation() |
80 | | - { |
81 | | - final ObjectDiffProperty annotation = readMethod.getAnnotation(ObjectDiffProperty.class); |
82 | | - return annotation != null && annotation.excluded(); |
83 | | - } |
| 73 | + public boolean isExcludedByAnnotation() { |
| 74 | + final ObjectDiffProperty annotation = readMethod.getAnnotation(ObjectDiffProperty.class); |
| 75 | + return annotation != null && annotation.excluded(); |
| 76 | + } |
84 | 77 |
|
85 | | - public String getPropertyName() |
86 | | - { |
87 | | - return this.propertyName; |
88 | | - } |
| 78 | + public String getPropertyName() { |
| 79 | + return this.propertyName; |
| 80 | + } |
89 | 81 |
|
90 | | - /** |
91 | | - * @return The annotations of the getter used to access this property. |
92 | | - */ |
93 | | - public Set<Annotation> getReadMethodAnnotations() |
94 | | - { |
95 | | - return new LinkedHashSet<Annotation>(asList(readMethod.getAnnotations())); |
96 | | - } |
| 82 | + /** |
| 83 | + * @return The annotations of the getter used to access this property. |
| 84 | + */ |
| 85 | + public Set<Annotation> getReadMethodAnnotations() { |
| 86 | + return new LinkedHashSet<Annotation>(asList(readMethod.getAnnotations())); |
| 87 | + } |
97 | 88 |
|
98 | | - public <T extends Annotation> T getReadMethodAnnotation(final Class<T> annotationClass) |
99 | | - { |
100 | | - final Set<? extends Annotation> annotations = getReadMethodAnnotations(); |
101 | | - assert (annotations != null) : "Something is wrong here. " + |
102 | | - "The contract of getReadAnnotations() guarantees a non-null return value."; |
103 | | - for (final Annotation annotation : annotations) |
104 | | - { |
105 | | - if (annotationClass.isAssignableFrom(annotation.annotationType())) |
106 | | - { |
107 | | - return annotationClass.cast(annotation); |
108 | | - } |
109 | | - } |
110 | | - return null; |
111 | | - } |
| 89 | + public <T extends Annotation> T getReadMethodAnnotation(final Class<T> annotationClass) { |
| 90 | + final Set<? extends Annotation> annotations = getReadMethodAnnotations(); |
| 91 | + assert (annotations != null) : "Something is wrong here. " |
| 92 | + + "The contract of getReadAnnotations() guarantees a non-null return value."; |
| 93 | + for (final Annotation annotation : annotations) { |
| 94 | + if (annotationClass.isAssignableFrom(annotation.annotationType())) { |
| 95 | + return annotationClass.cast(annotation); |
| 96 | + } |
| 97 | + } |
| 98 | + return null; |
| 99 | + } |
112 | 100 |
|
113 | | - public BeanPropertyElementSelector getElementSelector() |
114 | | - { |
115 | | - return new BeanPropertyElementSelector(this.propertyName); |
116 | | - } |
| 101 | + public BeanPropertyElementSelector getElementSelector() { |
| 102 | + return new BeanPropertyElementSelector(this.propertyName); |
| 103 | + } |
117 | 104 |
|
118 | | - public Object get(final Object target) |
119 | | - { |
120 | | - if (target == null) |
121 | | - { |
122 | | - return null; |
123 | | - } |
124 | | - try |
125 | | - { |
126 | | - return readMethod.invoke(target); |
127 | | - } |
128 | | - catch (final Exception cause) |
129 | | - { |
130 | | - throw new PropertyReadException(propertyName, target.getClass(), cause); |
131 | | - } |
132 | | - } |
| 105 | + public Object get(final Object target) { |
| 106 | + if (target == null) { |
| 107 | + return null; |
| 108 | + } |
| 109 | + try { |
| 110 | + return readMethod.invoke(target); |
| 111 | + } catch (final Exception cause) { |
| 112 | + throw new PropertyReadException(propertyName, target.getClass(), cause); |
| 113 | + } |
| 114 | + } |
133 | 115 |
|
134 | | - public void set(final Object target, final Object value) |
135 | | - { |
136 | | - if (target == null) |
137 | | - { |
138 | | - logger.info("Couldn't set new value '{}' for property '{}' " + |
139 | | - "because the target object is null", value, propertyName); |
140 | | - } |
141 | | - else if (writeMethod == null) |
142 | | - { |
143 | | - logger.debug("No setter found for property '{}'", propertyName); |
144 | | - tryToReplaceContentOfCollectionTypes(target, value); |
145 | | - } |
146 | | - else |
147 | | - { |
148 | | - invokeWriteMethod(target, value); |
149 | | - } |
150 | | - } |
| 116 | + public void set(final Object target, final Object value) { |
| 117 | + if (target == null) { |
| 118 | + logger.info("Couldn't set new value '{}' for property '{}' " + "because the target object is null", value, |
| 119 | + propertyName); |
| 120 | + } else if (writeMethod == null) { |
| 121 | + logger.debug("No setter found for property '{}'", propertyName); |
| 122 | + tryToReplaceContentOfCollectionTypes(target, value); |
| 123 | + } else { |
| 124 | + invokeWriteMethod(target, value); |
| 125 | + } |
| 126 | + } |
151 | 127 |
|
152 | | - public void unset(final Object target) |
153 | | - { |
154 | | - set(target, null); |
155 | | - } |
| 128 | + public void unset(final Object target) { |
| 129 | + set(target, null); |
| 130 | + } |
156 | 131 |
|
157 | | - @SuppressWarnings("unchecked") |
158 | | - private void tryToReplaceContentOfCollectionTypes(final Object target, final Object value) |
159 | | - { |
160 | | - if (Collection.class.isAssignableFrom(readMethod.getReturnType())) |
161 | | - { |
162 | | - if (tryToReplaceCollectionContent((Collection<Object>) get(target), (Collection<Object>) value)) |
163 | | - { |
164 | | - return; |
165 | | - } |
166 | | - } |
167 | | - if (Map.class.isAssignableFrom(readMethod.getReturnType())) |
168 | | - { |
169 | | - if (tryToReplaceMapContent((Map<Object, Object>) get(target), (Map<Object, Object>) value)) |
170 | | - { |
171 | | - return; |
172 | | - } |
173 | | - } |
174 | | - logger.info("Couldn't set new value '{}' for property '{}'", value, propertyName); |
175 | | - } |
| 132 | + @SuppressWarnings("unchecked") |
| 133 | + private void tryToReplaceContentOfCollectionTypes(final Object target, final Object value) { |
| 134 | + if (Collection.class.isAssignableFrom(readMethod.getReturnType())) { |
| 135 | + if (tryToReplaceCollectionContent((Collection<Object>) get(target), (Collection<Object>) value)) { |
| 136 | + return; |
| 137 | + } |
| 138 | + } |
| 139 | + if (Map.class.isAssignableFrom(readMethod.getReturnType())) { |
| 140 | + if (tryToReplaceMapContent((Map<Object, Object>) get(target), (Map<Object, Object>) value)) { |
| 141 | + return; |
| 142 | + } |
| 143 | + } |
| 144 | + logger.info("Couldn't set new value '{}' for property '{}'", value, propertyName); |
| 145 | + } |
176 | 146 |
|
177 | | - private void invokeWriteMethod(final Object target, final Object value) |
178 | | - { |
179 | | - try |
180 | | - { |
181 | | - writeMethod.invoke(target, value); |
182 | | - } |
183 | | - catch (final Exception cause) |
184 | | - { |
185 | | - throw new PropertyWriteException(propertyName, target.getClass(), value, cause); |
186 | | - } |
187 | | - } |
| 147 | + private void invokeWriteMethod(final Object target, final Object value) { |
| 148 | + try { |
| 149 | + writeMethod.invoke(target, value); |
| 150 | + } catch (final Exception cause) { |
| 151 | + throw new PropertyWriteException(propertyName, target.getClass(), value, cause); |
| 152 | + } |
| 153 | + } |
188 | 154 |
|
189 | | - private static boolean tryToReplaceCollectionContent(final Collection<Object> target, |
190 | | - final Collection<Object> value) |
191 | | - { |
192 | | - if (target == null) |
193 | | - { |
194 | | - return false; |
195 | | - } |
196 | | - try |
197 | | - { |
198 | | - target.clear(); |
199 | | - target.addAll(value); |
200 | | - return true; |
201 | | - } |
202 | | - catch (final Exception unmodifiable) |
203 | | - { |
204 | | - logger.debug("Failed to replace content of existing Collection", unmodifiable); |
205 | | - return false; |
206 | | - } |
207 | | - } |
| 155 | + private static boolean tryToReplaceCollectionContent(final Collection<Object> target, final Collection<Object> value) { |
| 156 | + if (target == null) { |
| 157 | + return false; |
| 158 | + } |
| 159 | + try { |
| 160 | + target.clear(); |
| 161 | + target.addAll(value); |
| 162 | + return true; |
| 163 | + } catch (final Exception unmodifiable) { |
| 164 | + logger.debug("Failed to replace content of existing Collection", unmodifiable); |
| 165 | + return false; |
| 166 | + } |
| 167 | + } |
208 | 168 |
|
209 | | - private static boolean tryToReplaceMapContent(final Map<Object, Object> target, |
210 | | - final Map<Object, Object> value) |
211 | | - { |
212 | | - if (target == null) |
213 | | - { |
214 | | - return false; |
215 | | - } |
216 | | - try |
217 | | - { |
218 | | - target.clear(); |
219 | | - target.putAll(value); |
220 | | - return true; |
221 | | - } |
222 | | - catch (final Exception unmodifiable) |
223 | | - { |
224 | | - logger.debug("Failed to replace content of existing Map", unmodifiable); |
225 | | - return false; |
226 | | - } |
227 | | - } |
| 169 | + private static boolean tryToReplaceMapContent(final Map<Object, Object> target, final Map<Object, Object> value) { |
| 170 | + if (target == null) { |
| 171 | + return false; |
| 172 | + } |
| 173 | + try { |
| 174 | + target.clear(); |
| 175 | + target.putAll(value); |
| 176 | + return true; |
| 177 | + } catch (final Exception unmodifiable) { |
| 178 | + logger.debug("Failed to replace content of existing Map", unmodifiable); |
| 179 | + return false; |
| 180 | + } |
| 181 | + } |
228 | 182 |
|
229 | | - public Class<?> getType() |
230 | | - { |
231 | | - return this.type; |
232 | | - } |
| 183 | + public Class<?> getType() { |
| 184 | + return this.type; |
| 185 | + } |
233 | 186 |
|
234 | | - @Override |
235 | | - public String toString() |
236 | | - { |
237 | | - final StringBuilder sb = new StringBuilder("PropertyAccessor{"); |
238 | | - sb.append("propertyName='").append(propertyName).append('\''); |
239 | | - sb.append(", type=").append(type.getCanonicalName()); |
240 | | - sb.append(", source=").append(readMethod.getDeclaringClass().getCanonicalName()); |
241 | | - sb.append(", hasWriteMethod=").append(writeMethod != null); |
242 | | - sb.append('}'); |
243 | | - return sb.toString(); |
244 | | - } |
| 187 | + @Override |
| 188 | + public String toString() { |
| 189 | + final StringBuilder sb = new StringBuilder("PropertyAccessor{"); |
| 190 | + sb.append("propertyName='").append(propertyName).append('\''); |
| 191 | + sb.append(", type=").append(type.getCanonicalName()); |
| 192 | + sb.append(", source=").append(readMethod.getDeclaringClass().getCanonicalName()); |
| 193 | + sb.append(", hasWriteMethod=").append(writeMethod != null); |
| 194 | + sb.append('}'); |
| 195 | + return sb.toString(); |
| 196 | + } |
245 | 197 |
|
246 | 198 | public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { |
247 | 199 | T ann = getReadMethodAnnotation(annotationClass); |
248 | 200 | if (ann != null) { |
249 | 201 | return ann; |
250 | 202 | } |
251 | | - return field.getAnnotation(annotationClass); |
| 203 | + return field == null ? null : field.getAnnotation(annotationClass); |
252 | 204 | } |
253 | 205 |
|
254 | 206 | public int getFieldModifiers() { |
255 | | - return field.getModifiers(); |
| 207 | + return field == null ? 0 : field.getModifiers(); |
256 | 208 | } |
257 | 209 |
|
258 | 210 | } |
0 commit comments