|
35 | 35 | import de.danielbechler.diff.selector.BeanPropertyElementSelector; |
36 | 36 | import de.danielbechler.util.Assert; |
37 | 37 |
|
38 | | -public class PropertyAccessor implements PropertyAwareAccessor { |
39 | | - private static final Logger logger = LoggerFactory.getLogger(PropertyAccessor.class); |
| 38 | +public class PropertyAccessor implements PropertyAwareAccessor |
| 39 | +{ |
| 40 | + private static final Logger logger = LoggerFactory.getLogger(PropertyAccessor.class); |
40 | 41 |
|
41 | | - private final String propertyName; |
42 | | - private final Class<?> type; |
43 | | - private final Method readMethod; |
44 | | - private final Method writeMethod; |
| 42 | + private final String propertyName; |
| 43 | + private final Class<?> type; |
| 44 | + private final Method readMethod; |
| 45 | + private final Method writeMethod; |
45 | 46 | private final Field field; |
46 | 47 |
|
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; |
| 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; |
51 | 53 | this.field = f; |
52 | | - this.readMethod = makeAccessible(readMethod); |
53 | | - this.writeMethod = makeAccessible(writeMethod); |
54 | | - this.type = this.readMethod.getReturnType(); |
55 | | - } |
| 54 | + this.readMethod = makeAccessible(readMethod); |
| 55 | + this.writeMethod = makeAccessible(writeMethod); |
| 56 | + this.type = this.readMethod.getReturnType(); |
| 57 | + } |
56 | 58 |
|
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 | | - } |
| 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 | + } |
64 | 68 |
|
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 | | - } |
| 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 | + } |
72 | 78 |
|
73 | | - public boolean isExcludedByAnnotation() { |
74 | | - final ObjectDiffProperty annotation = readMethod.getAnnotation(ObjectDiffProperty.class); |
75 | | - return annotation != null && annotation.excluded(); |
76 | | - } |
| 79 | + public boolean isExcludedByAnnotation() |
| 80 | + { |
| 81 | + final ObjectDiffProperty annotation = readMethod.getAnnotation(ObjectDiffProperty.class); |
| 82 | + return annotation != null && annotation.excluded(); |
| 83 | + } |
77 | 84 |
|
78 | | - public String getPropertyName() { |
79 | | - return this.propertyName; |
80 | | - } |
| 85 | + public String getPropertyName() |
| 86 | + { |
| 87 | + return this.propertyName; |
| 88 | + } |
81 | 89 |
|
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 | | - } |
| 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 | + } |
88 | 97 |
|
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 | | - } |
| 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 | + } |
100 | 112 |
|
101 | | - public BeanPropertyElementSelector getElementSelector() { |
102 | | - return new BeanPropertyElementSelector(this.propertyName); |
103 | | - } |
| 113 | + public BeanPropertyElementSelector getElementSelector() |
| 114 | + { |
| 115 | + return new BeanPropertyElementSelector(this.propertyName); |
| 116 | + } |
104 | 117 |
|
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 | | - } |
| 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 | + } |
115 | 133 |
|
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 | | - } |
| 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 | + } |
127 | 151 |
|
128 | | - public void unset(final Object target) { |
129 | | - set(target, null); |
130 | | - } |
| 152 | + public void unset(final Object target) |
| 153 | + { |
| 154 | + set(target, null); |
| 155 | + } |
131 | 156 |
|
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 | | - } |
| 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 | + } |
146 | 176 |
|
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 | | - } |
| 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 | + } |
154 | 188 |
|
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 | | - } |
| 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 | + } |
168 | 208 |
|
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 | | - } |
| 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 | + } |
182 | 228 |
|
183 | | - public Class<?> getType() { |
184 | | - return this.type; |
185 | | - } |
| 229 | + public Class<?> getType() |
| 230 | + { |
| 231 | + return this.type; |
| 232 | + } |
186 | 233 |
|
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 | | - } |
| 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 | + } |
197 | 245 |
|
198 | 246 | public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { |
199 | 247 | T ann = getReadMethodAnnotation(annotationClass); |
|
0 commit comments