/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation, and/or the GNU Lesser
* General Public License, version 2.1, also as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.rhq.test;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.beanutils.PropertyUtils;
public class PropertyMatcher<T> {
private T expected;
private T actual;
private Set<String> ignoredProperties = new HashSet<String>();
private Double maxDifference;
public void setExpected(T expected) {
this.expected = expected;
}
public void setActual(T actual) {
this.actual = actual;
}
public void setIgnoredProperties(Collection<String> ignoredProperties) {
this.ignoredProperties.addAll(ignoredProperties);
}
public void setMaxDifference(Double maxDifference) {
this.maxDifference = maxDifference;
}
public MatchResult execute() {
try {
Map<String, ?> expectedProps = PropertyUtils.describe(expected);
Map<String, ?> actualProps = PropertyUtils.describe(actual);
boolean isMatch = true;
StringBuilder details = new StringBuilder(expected.getClass().getSimpleName() +
" objects do not match:\n");
for (String name : expectedProps.keySet()) {
Object expectedValue = expectedProps.get(name);
Object actualValue = actualProps.get(name);
if (ignoredProperties.contains(name)) {
continue;
}
if (!propertyEquals(expectedValue, actualValue)) {
isMatch = false;
details.append("expected." + name + " = " + expectedValue + "\n");
details.append("actual." + name + " = " + actualValue + "\n\n");
}
}
return new MatchResult(isMatch, details.toString());
}
catch (IllegalAccessException e) {
throw new PropertyMatchException(e);
}
catch (InvocationTargetException e) {
throw new PropertyMatchException(e);
}
catch (NoSuchMethodException e) {
throw new PropertyMatchException(e);
}
}
private boolean propertyEquals(Object expected, Object actual) {
if (expected == null && actual == null) {
return true;
}
if (expected == null && actual != null) {
return false;
}
if (maxDifference != null && expected instanceof Double) {
boolean result = expected.equals(actual);
if (!result) {
Double dExpected = (Double) expected;
Double dActual = (Double) actual;
Double diff = Math.abs(dExpected - dActual);
result = ((!diff.isNaN()) && (!diff.isInfinite()) && (diff < maxDifference));
}
return result;
}
return expected.equals(actual);
}
}