Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fixed Exception for non JavaBean classes
  • Loading branch information
Wolfgang-Winter committed Dec 13, 2014
commit 562ad3d78aa52cbb3b0b81faa266ff17f2879c85
330 changes: 141 additions & 189 deletions src/main/java/de/danielbechler/diff/introspection/PropertyAccessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,224 +35,176 @@
import de.danielbechler.diff.selector.BeanPropertyElementSelector;
import de.danielbechler.util.Assert;

public class PropertyAccessor implements PropertyAwareAccessor
{
private static final Logger logger = LoggerFactory.getLogger(PropertyAccessor.class);
public class PropertyAccessor implements PropertyAwareAccessor {
private static final Logger logger = LoggerFactory.getLogger(PropertyAccessor.class);

private final String propertyName;
private final Class<?> type;
private final Method readMethod;
private final Method writeMethod;
private final String propertyName;
private final Class<?> type;
private final Method readMethod;
private final Method writeMethod;
private final Field field;

public PropertyAccessor(final String propertyName, final Field f, final Method readMethod, final Method writeMethod)
{
Assert.notNull(propertyName, "propertyName");
Assert.notNull(readMethod, "readMethod");
this.propertyName = propertyName;
public PropertyAccessor(final String propertyName, final Field f, final Method readMethod, final Method writeMethod) {
Assert.notNull(propertyName, "propertyName");
Assert.notNull(readMethod, "readMethod");
this.propertyName = propertyName;
this.field = f;
this.readMethod = makeAccessible(readMethod);
this.writeMethod = makeAccessible(writeMethod);
this.type = this.readMethod.getReturnType();
}
this.readMethod = makeAccessible(readMethod);
this.writeMethod = makeAccessible(writeMethod);
this.type = this.readMethod.getReturnType();
}

private static Method makeAccessible(final Method method)
{
if (method != null && !method.isAccessible())
{
logger.debug("Making method accessible: {}", method.toString());
method.setAccessible(true);
}
return method;
}
private static Method makeAccessible(final Method method) {
if (method != null && !method.isAccessible()) {
logger.debug("Making method accessible: {}", method.toString());
method.setAccessible(true);
}
return method;
}

public final Set<String> getCategoriesFromAnnotation()
{
final ObjectDiffProperty annotation = readMethod.getAnnotation(ObjectDiffProperty.class);
if (annotation != null)
{
return new TreeSet<String>(asList(annotation.categories()));
}
return Collections.emptySet();
}
public final Set<String> getCategoriesFromAnnotation() {
final ObjectDiffProperty annotation = readMethod.getAnnotation(ObjectDiffProperty.class);
if (annotation != null) {
return new TreeSet<String>(asList(annotation.categories()));
}
return Collections.emptySet();
}

public boolean isExcludedByAnnotation()
{
final ObjectDiffProperty annotation = readMethod.getAnnotation(ObjectDiffProperty.class);
return annotation != null && annotation.excluded();
}
public boolean isExcludedByAnnotation() {
final ObjectDiffProperty annotation = readMethod.getAnnotation(ObjectDiffProperty.class);
return annotation != null && annotation.excluded();
}

public String getPropertyName()
{
return this.propertyName;
}
public String getPropertyName() {
return this.propertyName;
}

/**
* @return The annotations of the getter used to access this property.
*/
public Set<Annotation> getReadMethodAnnotations()
{
return new LinkedHashSet<Annotation>(asList(readMethod.getAnnotations()));
}
/**
* @return The annotations of the getter used to access this property.
*/
public Set<Annotation> getReadMethodAnnotations() {
return new LinkedHashSet<Annotation>(asList(readMethod.getAnnotations()));
}

public <T extends Annotation> T getReadMethodAnnotation(final Class<T> annotationClass)
{
final Set<? extends Annotation> annotations = getReadMethodAnnotations();
assert (annotations != null) : "Something is wrong here. " +
"The contract of getReadAnnotations() guarantees a non-null return value.";
for (final Annotation annotation : annotations)
{
if (annotationClass.isAssignableFrom(annotation.annotationType()))
{
return annotationClass.cast(annotation);
}
}
return null;
}
public <T extends Annotation> T getReadMethodAnnotation(final Class<T> annotationClass) {
final Set<? extends Annotation> annotations = getReadMethodAnnotations();
assert (annotations != null) : "Something is wrong here. "
+ "The contract of getReadAnnotations() guarantees a non-null return value.";
for (final Annotation annotation : annotations) {
if (annotationClass.isAssignableFrom(annotation.annotationType())) {
return annotationClass.cast(annotation);
}
}
return null;
}

public BeanPropertyElementSelector getElementSelector()
{
return new BeanPropertyElementSelector(this.propertyName);
}
public BeanPropertyElementSelector getElementSelector() {
return new BeanPropertyElementSelector(this.propertyName);
}

public Object get(final Object target)
{
if (target == null)
{
return null;
}
try
{
return readMethod.invoke(target);
}
catch (final Exception cause)
{
throw new PropertyReadException(propertyName, target.getClass(), cause);
}
}
public Object get(final Object target) {
if (target == null) {
return null;
}
try {
return readMethod.invoke(target);
} catch (final Exception cause) {
throw new PropertyReadException(propertyName, target.getClass(), cause);
}
}

public void set(final Object target, final Object value)
{
if (target == null)
{
logger.info("Couldn't set new value '{}' for property '{}' " +
"because the target object is null", value, propertyName);
}
else if (writeMethod == null)
{
logger.debug("No setter found for property '{}'", propertyName);
tryToReplaceContentOfCollectionTypes(target, value);
}
else
{
invokeWriteMethod(target, value);
}
}
public void set(final Object target, final Object value) {
if (target == null) {
logger.info("Couldn't set new value '{}' for property '{}' " + "because the target object is null", value,
propertyName);
} else if (writeMethod == null) {
logger.debug("No setter found for property '{}'", propertyName);
tryToReplaceContentOfCollectionTypes(target, value);
} else {
invokeWriteMethod(target, value);
}
}

public void unset(final Object target)
{
set(target, null);
}
public void unset(final Object target) {
set(target, null);
}

@SuppressWarnings("unchecked")
private void tryToReplaceContentOfCollectionTypes(final Object target, final Object value)
{
if (Collection.class.isAssignableFrom(readMethod.getReturnType()))
{
if (tryToReplaceCollectionContent((Collection<Object>) get(target), (Collection<Object>) value))
{
return;
}
}
if (Map.class.isAssignableFrom(readMethod.getReturnType()))
{
if (tryToReplaceMapContent((Map<Object, Object>) get(target), (Map<Object, Object>) value))
{
return;
}
}
logger.info("Couldn't set new value '{}' for property '{}'", value, propertyName);
}
@SuppressWarnings("unchecked")
private void tryToReplaceContentOfCollectionTypes(final Object target, final Object value) {
if (Collection.class.isAssignableFrom(readMethod.getReturnType())) {
if (tryToReplaceCollectionContent((Collection<Object>) get(target), (Collection<Object>) value)) {
return;
}
}
if (Map.class.isAssignableFrom(readMethod.getReturnType())) {
if (tryToReplaceMapContent((Map<Object, Object>) get(target), (Map<Object, Object>) value)) {
return;
}
}
logger.info("Couldn't set new value '{}' for property '{}'", value, propertyName);
}

private void invokeWriteMethod(final Object target, final Object value)
{
try
{
writeMethod.invoke(target, value);
}
catch (final Exception cause)
{
throw new PropertyWriteException(propertyName, target.getClass(), value, cause);
}
}
private void invokeWriteMethod(final Object target, final Object value) {
try {
writeMethod.invoke(target, value);
} catch (final Exception cause) {
throw new PropertyWriteException(propertyName, target.getClass(), value, cause);
}
}

private static boolean tryToReplaceCollectionContent(final Collection<Object> target,
final Collection<Object> value)
{
if (target == null)
{
return false;
}
try
{
target.clear();
target.addAll(value);
return true;
}
catch (final Exception unmodifiable)
{
logger.debug("Failed to replace content of existing Collection", unmodifiable);
return false;
}
}
private static boolean tryToReplaceCollectionContent(final Collection<Object> target, final Collection<Object> value) {
if (target == null) {
return false;
}
try {
target.clear();
target.addAll(value);
return true;
} catch (final Exception unmodifiable) {
logger.debug("Failed to replace content of existing Collection", unmodifiable);
return false;
}
}

private static boolean tryToReplaceMapContent(final Map<Object, Object> target,
final Map<Object, Object> value)
{
if (target == null)
{
return false;
}
try
{
target.clear();
target.putAll(value);
return true;
}
catch (final Exception unmodifiable)
{
logger.debug("Failed to replace content of existing Map", unmodifiable);
return false;
}
}
private static boolean tryToReplaceMapContent(final Map<Object, Object> target, final Map<Object, Object> value) {
if (target == null) {
return false;
}
try {
target.clear();
target.putAll(value);
return true;
} catch (final Exception unmodifiable) {
logger.debug("Failed to replace content of existing Map", unmodifiable);
return false;
}
}

public Class<?> getType()
{
return this.type;
}
public Class<?> getType() {
return this.type;
}

@Override
public String toString()
{
final StringBuilder sb = new StringBuilder("PropertyAccessor{");
sb.append("propertyName='").append(propertyName).append('\'');
sb.append(", type=").append(type.getCanonicalName());
sb.append(", source=").append(readMethod.getDeclaringClass().getCanonicalName());
sb.append(", hasWriteMethod=").append(writeMethod != null);
sb.append('}');
return sb.toString();
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("PropertyAccessor{");
sb.append("propertyName='").append(propertyName).append('\'');
sb.append(", type=").append(type.getCanonicalName());
sb.append(", source=").append(readMethod.getDeclaringClass().getCanonicalName());
sb.append(", hasWriteMethod=").append(writeMethod != null);
sb.append('}');
return sb.toString();
}

public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
T ann = getReadMethodAnnotation(annotationClass);
if (ann != null) {
return ann;
}
return field.getAnnotation(annotationClass);
return field == null ? null : field.getAnnotation(annotationClass);
}

public int getFieldModifiers() {
return field.getModifiers();
return field == null ? 0 : field.getModifiers();
}

}
Loading