Skip to content

Commit 8056d9c

Browse files
committed
Polishing and improved test coverage of introspection package
1 parent 700c3a6 commit 8056d9c

10 files changed

+273
-75
lines changed

src/main/java/de/danielbechler/diff/introspection/DefaultPropertyAccessExceptionHandler.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,11 @@
2222

2323
public class DefaultPropertyAccessExceptionHandler implements PropertyAccessExceptionHandler
2424
{
25-
private static final Logger logger = LoggerFactory.getLogger(DefaultPropertyAccessExceptionHandler.class);
25+
Logger logger = LoggerFactory.getLogger(DefaultPropertyAccessExceptionHandler.class);
2626

2727
public DiffNode onPropertyWriteException(final PropertyWriteException exception, final DiffNode node)
2828
{
29-
final Object newValue = exception.getNewValue();
30-
final String propertyName = exception.getPropertyName();
31-
logger.info("Couldn't set new value '{}' for property '{}'", newValue, propertyName);
29+
logger.info(exception.getMessage());
3230
throw exception;
3331
}
3432

src/main/java/de/danielbechler/diff/introspection/PropertyAccessException.java

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,37 +23,23 @@ public abstract class PropertyAccessException extends RuntimeException
2323
{
2424
private static final long serialVersionUID = 1L;
2525

26-
private String propertyName;
27-
private Class<?> targetType;
26+
private final String propertyName;
27+
private final Class<?> targetType;
2828

29-
public PropertyAccessException(final Throwable cause)
29+
protected PropertyAccessException(final String propertyName, final Class<?> targetType, final Throwable cause)
3030
{
3131
super(cause);
32-
}
33-
34-
@Override
35-
public String getMessage()
36-
{
37-
return String.format("Property '%s' on target of type %s.", propertyName, targetType);
32+
this.propertyName = propertyName;
33+
this.targetType = targetType;
3834
}
3935

4036
public String getPropertyName()
4137
{
4238
return propertyName;
4339
}
4440

45-
public void setPropertyName(final String propertyName)
46-
{
47-
this.propertyName = propertyName;
48-
}
49-
5041
public Class<?> getTargetType()
5142
{
5243
return targetType;
5344
}
54-
55-
public void setTargetType(final Class<?> targetType)
56-
{
57-
this.targetType = targetType;
58-
}
5945
}

src/main/java/de/danielbechler/diff/introspection/PropertyAccessor.java

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,9 @@ public Object get(final Object target)
124124
{
125125
return readMethod.invoke(target);
126126
}
127-
catch (final Exception e)
127+
catch (final Exception cause)
128128
{
129-
final PropertyReadException ex = new PropertyReadException(e);
130-
ex.setPropertyName(propertyName);
131-
ex.setTargetType(target.getClass());
132-
throw ex;
129+
throw new PropertyReadException(propertyName, target.getClass(), cause);
133130
}
134131
}
135132

@@ -161,22 +158,23 @@ private void logFailedSet(final Object value)
161158
logger.info("Couldn't set new value '{}' for property '{}'", value, propertyName);
162159
}
163160

161+
@SuppressWarnings("unchecked")
164162
private void tryToReplaceContentOfCollectionTypes(final Object target, final Object value)
165163
{
166164
if (Collection.class.isAssignableFrom(readMethod.getReturnType()))
167165
{
168-
//noinspection unchecked
169-
tryToReplaceCollectionContent((Collection<Object>) get(target), (Collection<Object>) value);
170-
return;
166+
if (tryToReplaceCollectionContent((Collection<Object>) get(target), (Collection<Object>) value))
167+
{
168+
return;
169+
}
171170
}
172-
173171
if (Map.class.isAssignableFrom(readMethod.getReturnType()))
174172
{
175-
//noinspection unchecked
176-
tryToReplaceMapContent((Map<Object, Object>) get(target), (Map<Object, Object>) value);
177-
return;
173+
if (tryToReplaceMapContent((Map<Object, Object>) get(target), (Map<Object, Object>) value))
174+
{
175+
return;
176+
}
178177
}
179-
180178
logFailedSet(value);
181179
}
182180

@@ -186,12 +184,9 @@ private void invokeWriteMethod(final Object target, final Object value)
186184
{
187185
writeMethod.invoke(target, value);
188186
}
189-
catch (final Exception e)
187+
catch (final Exception cause)
190188
{
191-
final PropertyWriteException ex = new PropertyWriteException(e, value);
192-
ex.setPropertyName(propertyName);
193-
ex.setTargetType(getType());
194-
throw ex;
189+
throw new PropertyWriteException(propertyName, getType(), value, cause);
195190
}
196191
}
197192

@@ -243,6 +238,12 @@ public Class<?> getType()
243238
@Override
244239
public String toString()
245240
{
246-
return "property '" + propertyName + "'";
241+
final StringBuilder sb = new StringBuilder("PropertyAccessor{");
242+
sb.append("propertyName='").append(propertyName).append('\'');
243+
sb.append(", type=").append(type.getCanonicalName());
244+
sb.append(", source=").append(readMethod.getDeclaringClass().getCanonicalName());
245+
sb.append(", hasWriteMethod=").append(writeMethod != null);
246+
sb.append('}');
247+
return sb.toString();
247248
}
248249
}

src/main/java/de/danielbechler/diff/introspection/PropertyReadException.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ public class PropertyReadException extends PropertyAccessException
2323
{
2424
private static final long serialVersionUID = 1L;
2525

26-
public PropertyReadException(final Throwable cause)
26+
public PropertyReadException(final String propertyName, final Class<?> targetType, final Throwable cause)
2727
{
28-
super(cause);
28+
super(propertyName, targetType, cause);
2929
}
3030

3131
@Override
3232
public String getMessage()
3333
{
34-
return "Failed to invoke read method. " + super.getMessage();
34+
return String.format("Failed to read value from property '%s' of type '%s'", getPropertyName(), getTargetType().getCanonicalName());
3535
}
3636
}

src/main/java/de/danielbechler/diff/introspection/PropertyWriteException.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,20 @@
2222
public class PropertyWriteException extends PropertyAccessException
2323
{
2424
private static final long serialVersionUID = 1L;
25-
private Object newValue;
2625

27-
public PropertyWriteException(final Throwable cause, final Object newValue)
26+
@SuppressWarnings("TransientFieldNotInitialized")
27+
private final transient Object newValue;
28+
29+
public PropertyWriteException(final String propertyName, final Class<?> targetType, final Object newValue, final Throwable cause)
2830
{
29-
super(cause);
31+
super(propertyName, targetType, cause);
3032
this.newValue = newValue;
3133
}
3234

3335
@Override
3436
public String getMessage()
3537
{
36-
return "Error while invoking write method. " + super.getMessage();
38+
return String.format("Failed to write new value '%s' to property '%s' of type '%s'", newValue, getPropertyName(), getTargetType().getCanonicalName());
3739
}
3840

3941
public Object getNewValue()

src/test/java/de/danielbechler/diff/access/InstancesSpec.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,13 @@ class InstancesSpec extends Specification {
7676

7777
def "getType() returns most specific shared type for non-primitive objects (except for Map and Collection)"() {
7878
given:
79-
def instances = Instances.of(beanPropertyAccessor, working, base);
79+
def instances = Instances.of(propertyAccessor, working, base);
8080

8181
expect:
8282
instances.getType() == resultType
8383

8484
where:
85-
beanPropertyAccessor | working | base | resultType
85+
propertyAccessor | working | base | resultType
8686
RootAccessor.instance | BigInteger.ONE | BigDecimal.ONE | Number
8787
RootAccessor.instance | new LineNumberReader(new StringReader("")) | new BufferedReader(new StringReader("")) | BufferedReader
8888
RootAccessor.instance | new StringReader("") | new BufferedReader(new StringReader("")) | Reader
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2014 Daniel Bechler
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package de.danielbechler.diff.introspection
18+
19+
import de.danielbechler.diff.node.DiffNode
20+
import org.slf4j.Logger
21+
import spock.lang.Specification
22+
23+
/**
24+
* Created by Daniel Bechler.
25+
*/
26+
class DefaultPropertyAccessExceptionHandlerTest extends Specification {
27+
def exceptionHandler
28+
def diffNode = Mock(DiffNode)
29+
def logger = Mock(Logger)
30+
31+
def setup() {
32+
exceptionHandler = new DefaultPropertyAccessExceptionHandler()
33+
exceptionHandler.logger = logger
34+
}
35+
36+
def 'onPropertyReadException should rethrow the PropertyReadException'() {
37+
given:
38+
def readException = new PropertyReadException('foo', Object, null)
39+
when:
40+
exceptionHandler.onPropertyReadException(readException, diffNode)
41+
then:
42+
def thrownException = thrown(PropertyReadException)
43+
thrownException.is readException
44+
}
45+
46+
def 'onPropertyWriteException should rethrow the PropertyWriteException'() {
47+
given:
48+
def writeException = new PropertyWriteException('foo', Object, 'bar', null)
49+
when:
50+
exceptionHandler.onPropertyWriteException(writeException, diffNode)
51+
then:
52+
def thrownException = thrown(PropertyWriteException)
53+
thrownException.is writeException
54+
}
55+
56+
def 'onPropertyWriteException should log exception message'() {
57+
given:
58+
def writeException = new PropertyWriteException('foo', Object, 'bar', null)
59+
when:
60+
exceptionHandler.onPropertyWriteException(writeException, diffNode)
61+
then:
62+
1 * logger.info(writeException.message);
63+
and:
64+
thrown(PropertyWriteException)
65+
}
66+
}

0 commit comments

Comments
 (0)