/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.util.beancompare;
import java.util.Collections;
import java.util.List;
import org.joda.beans.MetaProperty;
import com.opengamma.util.ArgumentChecker;
/**
* Encapsulates the difference in a property's value between two instances of the same bean type. Contains the
* property that differs, the values from each bean and the path to the property (if it is a child bean of the
* bean at the root of the comparison).
*
* @param <P> Type of the field that differs between the two beans.
* @see BeanCompare#compare(org.joda.beans.Bean, org.joda.beans.Bean)
*/
public class BeanDifference<P> {
/** Property that differed between the two beans */
private final MetaProperty<? extends P> _property;
/** Path from the root bean to the bean where the difference was found, empty list if the property belongs to the root bean */
private final List<MetaProperty<?>> _path;
/** Property value in bean 1 */
private final P _value1;
/** Property value in bean 2 */
private final P _value2;
/**
* Creates an instance.
*
* @param property the property that differed between the two beans, not null
* @param value1 the value of the property in bean 1, can be null
* @param value2 the value of the property in bean 2, can be null
*/
public BeanDifference(MetaProperty<? extends P> property, P value1, P value2) {
this(property, value1, value2, Collections.<MetaProperty<?>>emptyList());
}
/**
* Creates an instance.
*
* @param property the property that differed between the two beans, not null
* @param value1 the value of the property in bean 1, can be null
* @param value2 the value of the property in bean 2, can be null
* @param path the path from the root bean to the bean where the difference was found,
* if the difference is in a property of the root bean this should be an empty list
*/
public BeanDifference(MetaProperty<? extends P> property, P value1, P value2, List<MetaProperty<?>> path) {
ArgumentChecker.notNull(property, "property");
ArgumentChecker.notNull(path, "path");
_property = property;
_value1 = value1;
_value2 = value2;
_path = path;
}
//-------------------------------------------------------------------------
/**
* Gets the property.
*
* @return the property which has a different value in the two beans
*/
public MetaProperty<? extends P> getProperty() {
return _property;
}
/**
* Gets the property value in the first bean.
*
* @return the property value in the first bean
*/
public P getValue1() {
return _value1;
}
/**
* Gets the property value in the second bean.
*
* @return the property value in the second bean
*/
public P getValue2() {
return _value2;
}
/**
* If any of a bean's properties are beans themselves the comparison recursively compares all beans in the hierarchy.
* If a difference is found in a child bean the path contains the properties leading from the root bean to the child.
* For example consider the following classes:
* <pre>
* class Foo implements Bean {
* @PropertyDefinition
* private Bar bar;
* }
*
* class Bar implements Bean {
* @PropertyDefinition
* private Baz baz;
* }
*
* class Baz implements Bean {
* @PropertyDefinition
* private String name;
* }
* </pre>
* Comparing two instances of {@code Foo} where {@code Baz} has a different name would yield a {@code BeanDifference}
* with a path {@code [Foo:bar, Bar:baz]} and a property {@code Baz:name}.
*
* @return the properties leading to the bean at the root of the comparison to the bean where
* the difference was found. Returns an empty list if the difference is in a property of the root bean.
*/
public List<MetaProperty<?>> getPath() {
return _path;
}
//-------------------------------------------------------------------------
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
BeanDifference<?> that = (BeanDifference<?>) obj;
if (!_path.equals(that._path)) {
return false;
}
if (!_property.equals(that._property)) {
return false;
}
if (_value1 != null ? !_value1.equals(that._value1) : that._value1 != null) {
return false;
}
if (_value2 != null ? !_value2.equals(that._value2) : that._value2 != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = _property.hashCode();
result = 31 * result + _path.hashCode();
result = 31 * result + (_value1 != null ? _value1.hashCode() : 0);
result = 31 * result + (_value2 != null ? _value2.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "BeanDifference{_property=" + _property + ", _value1=" + _value1 + ", _value2=" + _value2 + ", _path=" + _path + "}";
}
}