LANG-637: There should be a DifferenceBuilder with a ReflectionDifferenceBuilder implementation

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1561215 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Duncan Jones 2014-01-24 22:37:50 +00:00
parent 054f2f9160
commit ea47f03c4d
8 changed files with 1932 additions and 0 deletions

View File

@ -22,6 +22,7 @@
<body>
<release version="3.3" date="TBA" description="Bugfix and Feature release">
<action issue="LANG-637" type="add" dev="djones">There should be a DifferenceBuilder with a ReflectionDifferenceBuilder implementation</action>
<action issue="LANG-954" type="fix" due-to="Michael Keppler" dev="sebb">uncaught PatternSyntaxException in FastDateFormat on Android</action>
<action issue="LANG-956" type="update" dev="britter">Improve JavaDoc of WordUtils.wrap methods</action>
<action issue="LANG-944" type="add" dev="britter" due-to="Rekha Joshi">Add the Jaro-Winkler string distance algorithm to StringUtils</action>

View File

@ -0,0 +1,119 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang3.builder;
import java.lang.reflect.Type;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.reflect.TypeUtils;
import org.apache.commons.lang3.tuple.Pair;
/**
* <p>
* A {@code Diff} contains the differences between two {@link Diffable} class
* fields.
* </p>
*
* <p>
* Typically, {@code Diff}s are retrieved by using a {@link DiffBuilder} to
* produce a {@link DiffList}, containing the differences between two objects.
* </p>
*
*
* @param <T>
* The type of object contained within this {@code Diff}. Differences
* between primitive objects are stored as their Object wrapper
* equivalent.
* @since 3.3
* @version $Id$
*/
public abstract class Diff<T> extends Pair<T, T> {
private static final long serialVersionUID = 1L;
private final Type type;
private final String fieldName;
/**
* <p>
* Constructs a new {@code Diff} for the given field name.
* </p>
*
* @param fieldName
* the name of the field
*/
protected Diff(String fieldName) {
this.type = ObjectUtils.defaultIfNull(
TypeUtils.getTypeArguments(getClass(), Diff.class).get(
Diff.class.getTypeParameters()[0]), Object.class);
this.fieldName = fieldName;
}
/**
* <p>
* Returns the type of the field.
* </p>
*
* @return the field type
*/
public final Type getType() {
return type;
}
/**
* <p>
* Returns the name of the field.
* </p>
*
* @return the field name
*/
public final String getFieldName() {
return fieldName;
}
/**
* <p>
* Returns a {@code String} representation of the {@code Diff}, with the
* following format:
*
* <pre>
* [fieldname: left-value, right-value]
* </pre>
*
* </p>
*
* @return the string representation
*/
@Override
public final String toString() {
return String.format("[%s: %s, %s]", fieldName, getLeft(), getRight());
}
/**
* <p>
* Throws {@code UnsupportedOperationException}.
* </p>
*
* @param value
* ignored
* @return nothing
*/
@Override
public final T setValue(T value) {
throw new UnsupportedOperationException("Cannot alter Diff object.");
}
}

View File

@ -0,0 +1,914 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang3.builder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
/**
* <p>
* Assists in implementing {@link Diffable#diff(Object)} methods.
* </p>
*
* <p>
* To use this class, write code as follows:
* </p>
*
* <pre>
* public class Person implements Diffable&lt;Person&gt; {
* String name;
* int age;
* boolean smoker;
*
* ...
*
* public DiffList diff(Person obj) {
* // No need for null check, as NullPointerException correct if obj is null
* return new DiffBuilder(this, obj, ToStringStyle.SHORT_PREFIX_STYLE)
* .append("name", this.name, obj.name)
* .append("age", this.age, obj.age)
* .append("smoker", this.smoker, obj.smoker)
* .build();
* }
* }
* </pre>
*
* <p>
* The {@code ToStringStyle} passed to the constructor is embedded in the
* returned {@code DiffList} and influences the style of the
* {@code DiffList.toString()} method. This style choice can be overridden by
* calling {@link DiffList#toString(ToStringStyle)}.
* </p>
*
* @since 3.3
* @version $Id$
* @see Diffable
* @see Diff
* @see DiffList
* @see ToStringStyle
*/
public class DiffBuilder implements Builder<DiffList> {
private final List<Diff<?>> diffs;
private final boolean objectsTriviallyEqual;
private final Object lhs;
private final Object rhs;
private final ToStringStyle style;
/**
* <p>
* Constructs a builder for the specified objects with the specified style.
* </p>
*
* <p>
* If {@code lhs == rhs} or {@code lhs.equals(rhs)} then the builder will
* not evaluate any calls to {@code append(...)} and will return an empty
* {@link DiffList} when {@link #build()} is executed.
* </p>
*
* @param lhs
* {@code this} object
* @param rhs
* the object to diff against
* @param style
* the style will use when outputting the objects, {@code null}
* uses the default
* @throws IllegalArgumentException
* if {@code lhs} or {@code rhs} is {@code null}
*/
public DiffBuilder(final Object lhs, final Object rhs,
final ToStringStyle style) {
if (lhs == null) {
throw new IllegalArgumentException("lhs cannot be null");
}
if (rhs == null) {
throw new IllegalArgumentException("rhs cannot be null");
}
this.diffs = new ArrayList<Diff<?>>();
this.lhs = lhs;
this.rhs = rhs;
this.style = style;
// Don't compare any fields if objects equal
this.objectsTriviallyEqual = (lhs == rhs || lhs.equals(rhs));
}
/**
* <p>
* Test if two {@code boolean}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code boolean}
* @param rhs
* the right hand {@code boolean}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final boolean lhs,
final boolean rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (lhs != rhs) {
diffs.add(new Diff<Boolean>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Boolean getLeft() {
return Boolean.valueOf(lhs);
}
@Override
public Boolean getRight() {
return Boolean.valueOf(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code boolean[]}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code boolean[]}
* @param rhs
* the right hand {@code boolean[]}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final boolean[] lhs,
final boolean[] rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (!Arrays.equals(lhs, rhs)) {
diffs.add(new Diff<Boolean[]>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Boolean[] getLeft() {
return ArrayUtils.toObject(lhs);
}
@Override
public Boolean[] getRight() {
return ArrayUtils.toObject(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code byte}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code byte}
* @param rhs
* the right hand {@code byte}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final byte lhs,
final byte rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (lhs != rhs) {
diffs.add(new Diff<Byte>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Byte getLeft() {
return Byte.valueOf(lhs);
}
@Override
public Byte getRight() {
return Byte.valueOf(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code byte[]}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code byte[]}
* @param rhs
* the right hand {@code byte[]}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final byte[] lhs,
final byte[] rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (!Arrays.equals(lhs, rhs)) {
diffs.add(new Diff<Byte[]>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Byte[] getLeft() {
return ArrayUtils.toObject(lhs);
}
@Override
public Byte[] getRight() {
return ArrayUtils.toObject(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code char}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code char}
* @param rhs
* the right hand {@code char}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final char lhs,
final char rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (lhs != rhs) {
diffs.add(new Diff<Character>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Character getLeft() {
return Character.valueOf(lhs);
}
@Override
public Character getRight() {
return Character.valueOf(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code char[]}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code char[]}
* @param rhs
* the right hand {@code char[]}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final char[] lhs,
final char[] rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (!Arrays.equals(lhs, rhs)) {
diffs.add(new Diff<Character[]>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Character[] getLeft() {
return ArrayUtils.toObject(lhs);
}
@Override
public Character[] getRight() {
return ArrayUtils.toObject(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code double}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code double}
* @param rhs
* the right hand {@code double}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final double lhs,
final double rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (Double.doubleToLongBits(lhs) != Double.doubleToLongBits(rhs)) {
diffs.add(new Diff<Double>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Double getLeft() {
return Double.valueOf(lhs);
}
@Override
public Double getRight() {
return Double.valueOf(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code double[]}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code double[]}
* @param rhs
* the right hand {@code double[]}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final double[] lhs,
final double[] rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (!Arrays.equals(lhs, rhs)) {
diffs.add(new Diff<Double[]>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Double[] getLeft() {
return ArrayUtils.toObject(lhs);
}
@Override
public Double[] getRight() {
return ArrayUtils.toObject(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code float}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code float}
* @param rhs
* the right hand {@code float}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final float lhs,
final float rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (Float.floatToIntBits(lhs) != Float.floatToIntBits(rhs)) {
diffs.add(new Diff<Float>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Float getLeft() {
return Float.valueOf(lhs);
}
@Override
public Float getRight() {
return Float.valueOf(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code float[]}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code float[]}
* @param rhs
* the right hand {@code float[]}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final float[] lhs,
final float[] rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (!Arrays.equals(lhs, rhs)) {
diffs.add(new Diff<Float[]>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Float[] getLeft() {
return ArrayUtils.toObject(lhs);
}
@Override
public Float[] getRight() {
return ArrayUtils.toObject(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code int}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code int}
* @param rhs
* the right hand {@code int}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final int lhs,
final int rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (lhs != rhs) {
diffs.add(new Diff<Integer>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Integer getLeft() {
return Integer.valueOf(lhs);
}
@Override
public Integer getRight() {
return Integer.valueOf(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code int[]}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code int[]}
* @param rhs
* the right hand {@code int[]}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final int[] lhs,
final int[] rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (!Arrays.equals(lhs, rhs)) {
diffs.add(new Diff<Integer[]>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Integer[] getLeft() {
return ArrayUtils.toObject(lhs);
}
@Override
public Integer[] getRight() {
return ArrayUtils.toObject(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code long}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code long}
* @param rhs
* the right hand {@code long}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final long lhs,
final long rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (lhs != rhs) {
diffs.add(new Diff<Long>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Long getLeft() {
return Long.valueOf(lhs);
}
@Override
public Long getRight() {
return Long.valueOf(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code long[]}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code long[]}
* @param rhs
* the right hand {@code long[]}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final long[] lhs,
final long[] rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (!Arrays.equals(lhs, rhs)) {
diffs.add(new Diff<Long[]>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Long[] getLeft() {
return ArrayUtils.toObject(lhs);
}
@Override
public Long[] getRight() {
return ArrayUtils.toObject(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code short}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code short}
* @param rhs
* the right hand {@code short}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final short lhs,
final short rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (lhs != rhs) {
diffs.add(new Diff<Short>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Short getLeft() {
return Short.valueOf(lhs);
}
@Override
public Short getRight() {
return Short.valueOf(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code short[]}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code short[]}
* @param rhs
* the right hand {@code short[]}
* @return this
* @throws IllegalArgumentException
* if field name is {@code null}
*/
public DiffBuilder append(final String fieldName, final short[] lhs,
final short[] rhs) {
if (fieldName == null) {
throw new IllegalArgumentException("Field name cannot be null");
}
if (objectsTriviallyEqual) {
return this;
}
if (!Arrays.equals(lhs, rhs)) {
diffs.add(new Diff<Short[]>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Short[] getLeft() {
return ArrayUtils.toObject(lhs);
}
@Override
public Short[] getRight() {
return ArrayUtils.toObject(rhs);
}
});
}
return this;
}
/**
* <p>
* Test if two {@code Objects}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code Object}
* @param rhs
* the right hand {@code Object}
* @return this
*/
public DiffBuilder append(final String fieldName, final Object lhs,
final Object rhs) {
if (objectsTriviallyEqual) {
return this;
}
if (lhs == rhs) {
return this;
}
Object objectToTest;
if (lhs != null) {
objectToTest = lhs;
} else {
// rhs cannot be null, as lhs != rhs
objectToTest = rhs;
}
if (objectToTest.getClass().isArray()) {
if (objectToTest instanceof boolean[]) {
return append(fieldName, (boolean[]) lhs, (boolean[]) rhs);
}
if (objectToTest instanceof byte[]) {
return append(fieldName, (byte[]) lhs, (byte[]) rhs);
}
if (objectToTest instanceof char[]) {
return append(fieldName, (char[]) lhs, (char[]) rhs);
}
if (objectToTest instanceof double[]) {
return append(fieldName, (double[]) lhs, (double[]) rhs);
}
if (objectToTest instanceof float[]) {
return append(fieldName, (float[]) lhs, (float[]) rhs);
}
if (objectToTest instanceof int[]) {
return append(fieldName, (int[]) lhs, (int[]) rhs);
}
if (objectToTest instanceof long[]) {
return append(fieldName, (long[]) lhs, (long[]) rhs);
}
if (objectToTest instanceof short[]) {
return append(fieldName, (short[]) lhs, (short[]) rhs);
}
return append(fieldName, (Object[]) lhs, (Object[]) rhs);
}
// Not array type
diffs.add(new Diff<Object>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Object getLeft() {
return lhs;
}
@Override
public Object getRight() {
return rhs;
}
});
return this;
}
/**
* <p>
* Test if two {@code Object[]}s are equal.
* </p>
*
* @param fieldName
* the field name
* @param lhs
* the left hand {@code Object[]}
* @param rhs
* the right hand {@code Object[]}
* @return this
*/
public DiffBuilder append(final String fieldName, final Object[] lhs,
final Object[] rhs) {
if (objectsTriviallyEqual) {
return this;
}
if (!Arrays.equals(lhs, rhs)) {
diffs.add(new Diff<Object[]>(fieldName) {
private static final long serialVersionUID = 1L;
@Override
public Object[] getLeft() {
return lhs;
}
@Override
public Object[] getRight() {
return rhs;
}
});
}
return this;
}
/**
* <p>
* Builds a {@link DiffList} based on the differences appended to this
* builder.
* </p>
*
* @return a {@code DiffList} containing the differences between the two
* objects.
*/
@Override
public DiffList build() {
return new DiffList(lhs, rhs, diffs, style);
}
}

View File

@ -0,0 +1,208 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang3.builder;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* <p>
* A {@code DiffList} contains a list of the differences between two
* {@link Diffable} objects. Typically these differences are displayed using
* {@link #toString()} method, which returns a string describing the fields that
* differ between the objects.
* </p>
* <p>
* Use a {@link DiffBuilder} to build a {@code DiffList} comparing two objects.
* </p>
*
* @since 3.3
* @version $Id$
*/
public class DiffList implements Iterable<Diff<?>> {
/**
* <p>
* The {@code String} returned when the objects have no differences:
* {@value}
* </p>
*/
public static final String OBJECTS_SAME_STRING = "";
private static final String DIFFERS_STRING = "differs from";
private final List<Diff<?>> diffs;
private final Object lhs;
private final Object rhs;
private final ToStringStyle style;
/**
* <p>
* Creates a {@link DiffList} containing the differences between two
* objects.
* </p>
*
* @param lhs
* the left hand object
* @param rhs
* the right hand object
* @param diffs
* the list of differences, may be empty
* @param style
* the style to use for the {@link #toString()} method. May be
* {@code null}, in which case
* {@link ToStringStyle#DEFAULT_STYLE} is used
* @throws IllegalArgumentException
* if {@code lhs}, {@code rhs} or {@code diffs} is {@code null}
*/
DiffList(final Object lhs, final Object rhs, final List<Diff<?>> diffs,
final ToStringStyle style) {
if (lhs == null) {
throw new IllegalArgumentException(
"Left hand object cannot be null");
}
if (rhs == null) {
throw new IllegalArgumentException(
"Right hand object cannot be null");
}
if (diffs == null) {
throw new IllegalArgumentException(
"List of differences cannot be null");
}
this.diffs = diffs;
this.lhs = lhs;
this.rhs = rhs;
if (style == null) {
this.style = ToStringStyle.DEFAULT_STYLE;
} else {
this.style = style;
}
}
/**
* <p>
* Returns an unmodifiable list of {@code Diff}s. The list may be empty if
* there were no differences between the objects.
* </p>
*
* @return an unmodifiable list of {@code Diff}s
*/
public List<Diff<?>> getDiffs() {
return Collections.unmodifiableList(diffs);
}
/**
* <p>
* Returns the number of differences between the two objects.
* </p>
*
* @return the number of differences
*/
public int getNumberOfDiffs() {
return diffs.size();
}
/**
* <p>
* Returns the style used by the {@link #toString()} method.
* </p>
*
* @return the style
*/
public ToStringStyle getToStringStyle() {
return style;
}
/**
* <p>
* Builds a {@code String} description of the differences contained within
* this {@code DiffList}. A {@link ToStringBuilder} is used for each object
* and the style of the output is governed by the {@code ToStringStyle}
* passed to the constructor.
* </p>
*
* <p>
* If there are no differences stored in this list, the method will return
* {@link #OBJECTS_SAME_STRING}. Otherwise, using the example given in
* {@link Diffable} and {@link ToStringStyle#SHORT_PREFIX_STYLE}, an output
* might be:
* </p>
*
* <pre>
* Person[name=John Doe,age=32] differs from Person[name=Joe Bloggs,age=26]
* </pre>
*
* <p>
* This indicates that the objects differ in name and age, but not in
* smoking status.
* </p>
*
* <p>
* To use a different {@code ToStringStyle} for an instance of this class,
* use {@link #toString(ToStringStyle)}.
* </p>
*
* @return a {@code String} description of the differences.
*/
@Override
public String toString() {
return toString(style);
}
/**
* <p>
* Builds a {@code String} description of the differences contained within
* this {@code DiffList}, using the supplied {@code ToStringStyle}.
* </p>
*
* @param style
* the {@code ToStringStyle} to use when outputting the objects
*
* @return a {@code String} description of the differences.
*/
public String toString(ToStringStyle style) {
if (diffs.size() == 0) {
return OBJECTS_SAME_STRING;
}
ToStringBuilder lhsBuilder = new ToStringBuilder(lhs, style);
ToStringBuilder rhsBuilder = new ToStringBuilder(rhs, style);
for (Diff<?> diff : diffs) {
lhsBuilder.append(diff.getFieldName(), diff.getLeft());
rhsBuilder.append(diff.getFieldName(), diff.getRight());
}
return String.format("%s %s %s", lhsBuilder.build(), DIFFERS_STRING,
rhsBuilder.build());
}
/**
* <p>
* Returns an iterator over the {@code Diff} objects contained in this list.
* </p>
*
* @return the iterator
*/
@Override
public Iterator<Diff<?>> iterator() {
return diffs.iterator();
}
}

View File

@ -0,0 +1,54 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang3.builder;
/**
* <p>{@code Diffable} classes can be compared with other objects
* for differences. The {@link DiffList} object retrieved can be queried
* for a list of differences or printed using the {@link DiffList#toString()}.</p>
*
* <p>The calculation of the differences is <i>consistent with equals</i> if
* and only if {@code d1.equals(d2)} implies {@code d1.diff(d2) == ""}.
* It is strongly recommended that implementations are consistent with equals
* to avoid confusion. Note that {@code null} is not an instance of any class
* and {@code d1.diff(null)} should throw a {@code NullPointerException}.</p>
*
* <p>
* {@code Diffable} classes lend themselves well to unit testing, in which a
* easily readable description of the differences between an anticipated result and
* an actual result can be retrieved. For example:
* </p>
* <pre>
* Assert.assertEquals(expected.diff(result), expected, result);
* </pre>
*
* @param <T> the type of objects that this object may be differentiated against
* @since 3.3
* @version $Id$
*/
public interface Diffable<T> {
/**
* <p>Retrieves a list of the differences between
* this object and the supplied object.</p>
*
* @param obj the object to diff against, can be {@code null}
* @return a list of differences
* @throws NullPointerException if the specified object is {@code null}
*/
DiffList diff(T obj);
}

View File

@ -0,0 +1,415 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang3.builder;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import org.apache.commons.lang3.ArrayUtils;
import org.junit.Test;
/**
* Unit tests {@link DiffBuilder}.
*
* @version $Id$
*/
public class DiffBuilderTest {
private static final ToStringStyle SHORT_STYLE = ToStringStyle.SHORT_PREFIX_STYLE;
private static class TypeTestClass implements Diffable<TypeTestClass> {
private ToStringStyle style = SHORT_STYLE;
private boolean booleanField = true;
private boolean[] booleanArrayField = {true};
private byte byteField = (byte) 0xFF;
private byte[] byteArrayField = {(byte) 0xFF};
private char charField = 'a';
private char[] charArrayField = {'a'};
private double doubleField = 1.0;
private double[] doubleArrayField = {1.0};
private float floatField = 1.0f;
private float[] floatArrayField = {1.0f};
private int intField = 1;
private int[] intArrayField = {1};
private long longField = 1L;
private long[] longArrayField = {1L};
private short shortField = 1;
private short[] shortArrayField = {1};
private Object objectField = null;
private Object[] objectArrayField = {null};
@Override
public DiffList diff(TypeTestClass obj) {
return new DiffBuilder(this, obj, style)
.append("boolean", booleanField, obj.booleanField)
.append("booleanArray", booleanArrayField, obj.booleanArrayField)
.append("byte", byteField, obj.byteField)
.append("byteArray", byteArrayField, obj.byteArrayField)
.append("char", charField, obj.charField)
.append("charArray", charArrayField, obj.charArrayField)
.append("double", doubleField, obj.doubleField)
.append("doubleArray", doubleArrayField, obj.doubleArrayField)
.append("float", floatField, obj.floatField)
.append("floatArray", floatArrayField, obj.floatArrayField)
.append("int", intField, obj.intField)
.append("intArray", intArrayField, obj.intArrayField)
.append("long", longField, obj.longField)
.append("longArray", longArrayField, obj.longArrayField)
.append("short", shortField, obj.shortField)
.append("shortArray", shortArrayField, obj.shortArrayField)
.append("objectField", objectField, obj.objectField)
.append("objectArrayField", objectArrayField, obj.objectArrayField)
.build();
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this, false);
}
@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj, false);
}
}
@Test
public void testBoolean() {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.booleanField = false;
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertEquals(Boolean.class, diff.getType());
assertEquals(Boolean.TRUE, diff.getLeft());
assertEquals(Boolean.FALSE, diff.getRight());
}
@Test
public void testBooleanArray() throws Exception {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.booleanArrayField = new boolean[] {false, false};
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertArrayEquals(ArrayUtils.toObject(class1.booleanArrayField),
(Object[]) diff.getLeft());
assertArrayEquals(ArrayUtils.toObject(class2.booleanArrayField),
(Object[]) diff.getRight());
}
@Test
public void testByte() {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.byteField = 0x01;
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertEquals(Byte.valueOf(class1.byteField), diff.getLeft());
assertEquals(Byte.valueOf(class2.byteField), diff.getRight());
}
@Test
public void testByteArray() throws Exception {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.byteArrayField= new byte[] {0x01, 0x02};
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertArrayEquals(ArrayUtils.toObject(class1.byteArrayField),
(Object[]) diff.getLeft());
assertArrayEquals(ArrayUtils.toObject(class2.byteArrayField),
(Object[]) diff.getRight());
}
@Test
public void testChar() {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.charField = 'z';
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertEquals(Character.valueOf(class1.charField), diff.getLeft());
assertEquals(Character.valueOf(class2.charField), diff.getRight());
}
@Test
public void testCharArray() throws Exception {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.charArrayField = new char[] {'f', 'o', 'o'};
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertArrayEquals(ArrayUtils.toObject(class1.charArrayField),
(Object[]) diff.getLeft());
assertArrayEquals(ArrayUtils.toObject(class2.charArrayField),
(Object[]) diff.getRight());
}
@Test
public void testDouble() {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.doubleField = 99.99;
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertEquals(Double.valueOf(class1.doubleField), diff.getLeft());
assertEquals(Double.valueOf(class2.doubleField), diff.getRight());
}
@Test
public void testDoubleArray() throws Exception {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.doubleArrayField = new double[] {3.0, 2.9, 2.8};
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertArrayEquals(ArrayUtils.toObject(class1.doubleArrayField),
(Object[]) diff.getLeft());
assertArrayEquals(ArrayUtils.toObject(class2.doubleArrayField),
(Object[]) diff.getRight());
}
@Test
public void testFloat() {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.floatField = 99.99F;
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertEquals(Float.valueOf(class1.floatField), diff.getLeft());
assertEquals(Float.valueOf(class2.floatField), diff.getRight());
}
@Test
public void testFloatArray() throws Exception {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.floatArrayField = new float[] {3.0F, 2.9F, 2.8F};
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertArrayEquals(ArrayUtils.toObject(class1.floatArrayField),
(Object[]) diff.getLeft());
assertArrayEquals(ArrayUtils.toObject(class2.floatArrayField),
(Object[]) diff.getRight());
}
@Test
public void testInt() {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.intField = 42;
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertEquals(Integer.valueOf(class1.intField), diff.getLeft());
assertEquals(Integer.valueOf(class2.intField), diff.getRight());
}
@Test
public void testIntArray() throws Exception {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.intArrayField = new int[] {3, 2, 1};
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertArrayEquals(ArrayUtils.toObject(class1.intArrayField),
(Object[]) diff.getLeft());
assertArrayEquals(ArrayUtils.toObject(class2.intArrayField),
(Object[]) diff.getRight());
}
@Test
public void testLong() {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.longField = 42L;
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertEquals(Long.valueOf(class1.longField), diff.getLeft());
assertEquals(Long.valueOf(class2.longField), diff.getRight());
}
@Test
public void testLongArray() throws Exception {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.longArrayField = new long[] {3L, 2L, 1L};
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertArrayEquals(ArrayUtils.toObject(class1.longArrayField),
(Object[]) diff.getLeft());
assertArrayEquals(ArrayUtils.toObject(class2.longArrayField),
(Object[]) diff.getRight());
}
@Test
public void testShort() {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.shortField = 42;
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertEquals(Short.valueOf(class1.shortField), diff.getLeft());
assertEquals(Short.valueOf(class2.shortField), diff.getRight());
}
@Test
public void testShortArray() throws Exception {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.shortArrayField = new short[] {3, 2, 1};
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertArrayEquals(ArrayUtils.toObject(class1.shortArrayField),
(Object[]) diff.getLeft());
assertArrayEquals(ArrayUtils.toObject(class2.shortArrayField),
(Object[]) diff.getRight());
}
@Test
public void testObject() throws Exception {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.objectField = "Some string";
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertEquals(class1.objectField, diff.getLeft());
assertEquals(class2.objectField, diff.getRight());
}
@Test
public void testObjectsEqual() throws Exception {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class1.objectField = "Some string";
class2.objectField = "Some string";
DiffList list = class1.diff(class2);
assertEquals(0, list.getNumberOfDiffs());
}
@Test
public void testObjectArray() throws Exception {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class2.objectArrayField = new Object[] {"string", 1, 2};
DiffList list = class1.diff(class2);
assertEquals(1, list.getNumberOfDiffs());
Diff<?> diff = list.getDiffs().get(0);
assertArrayEquals(class1.objectArrayField, (Object[]) diff.getLeft());
assertArrayEquals(class2.objectArrayField, (Object[]) diff.getRight());
}
@Test
public void testObjectArrayEqual() throws Exception {
TypeTestClass class1 = new TypeTestClass();
TypeTestClass class2 = new TypeTestClass();
class1.objectArrayField = new Object[] {"string", 1, 2};
class2.objectArrayField = new Object[] {"string", 1, 2};
DiffList list = class1.diff(class2);
assertEquals(0, list.getNumberOfDiffs());
}
@Test
public void testByteArrayEqualAsObject() throws Exception {
DiffList list = new DiffBuilder("String1", "String2", SHORT_STYLE)
.append("foo", (Object) new boolean[] {false}, (Object) new boolean[] {false})
.append("foo", (Object) new byte[] {0x01}, (Object) new byte[] {0x01})
.append("foo", (Object) new char[] {'a'}, (Object) new char[] {'a'})
.append("foo", (Object) new double[] {1.0}, (Object) new double[] {1.0})
.append("foo", (Object) new float[] {1.0F}, (Object) new float[] {1.0F})
.append("foo", (Object) new int[] {1}, (Object) new int[] {1})
.append("foo", (Object) new long[] {1L}, (Object) new long[] {1L})
.append("foo", (Object) new short[] {1}, (Object) new short[] {1})
.append("foo", (Object) new Object[] {1, "two"}, (Object) new Object[] {1, "two"})
.build();
assertEquals(0, list.getNumberOfDiffs());
}
@Test(expected=IllegalArgumentException.class)
public void testNullLhs() {
new DiffBuilder(null, this, ToStringStyle.DEFAULT_STYLE);
}
@Test(expected=IllegalArgumentException.class)
public void testNullRhs() {
new DiffBuilder(this, null, ToStringStyle.DEFAULT_STYLE);
}
@Test
public void testSameObjectIgnoresAppends() {
TypeTestClass testClass = new TypeTestClass();
DiffList list = new DiffBuilder(testClass, testClass, SHORT_STYLE)
.append("ignored", false, true)
.build();
assertEquals(0, list.getNumberOfDiffs());
}
@Test
public void testSimilarObjectIgnoresAppends() {
TypeTestClass testClass1 = new TypeTestClass();
TypeTestClass testClass2 = new TypeTestClass();
DiffList list = new DiffBuilder(testClass1, testClass2, SHORT_STYLE)
.append("ignored", false, true)
.build();
assertEquals(0, list.getNumberOfDiffs());
}
@Test
public void testStylePassedToDiffList() {
TypeTestClass class1 = new TypeTestClass();
DiffList list = class1.diff(class1);
assertEquals(SHORT_STYLE, list.getToStringStyle());
class1.style = ToStringStyle.MULTI_LINE_STYLE;
list = class1.diff(class1);
assertEquals(ToStringStyle.MULTI_LINE_STYLE, list.getToStringStyle());
}
}

View File

@ -0,0 +1,149 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang3.builder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
/**
* Unit tests {@link DiffList}.
*
* @version $Id$
*/
public class DiffListTest {
private static final SimpleClass SIMPLE_FALSE = new SimpleClass(false);
private static final SimpleClass SIMPLE_TRUE = new SimpleClass(true);
private static final ToStringStyle SHORT_STYLE = ToStringStyle.SHORT_PREFIX_STYLE;
private static class SimpleClass implements Diffable<SimpleClass> {
private boolean booleanField;
public SimpleClass(boolean booleanField) {
this.booleanField = booleanField;
}
public static String getFieldName() {
return "booleanField";
}
@Override
public DiffList diff(SimpleClass obj) {
return new DiffBuilder(this, obj, ToStringStyle.SHORT_PREFIX_STYLE)
.append(getFieldName(), booleanField, obj.booleanField)
.build();
}
}
private static class EmptyClass {
}
@Test(expected = UnsupportedOperationException.class)
public void testListIsNonModifiable() {
SimpleClass lhs = new SimpleClass(true);
SimpleClass rhs = new SimpleClass(false);
List<Diff<?>> diffs = lhs.diff(rhs).getDiffs();
DiffList list = new DiffList(lhs, rhs, diffs, SHORT_STYLE);
assertEquals(diffs, list.getDiffs());
assertEquals(1, list.getNumberOfDiffs());
list.getDiffs().remove(0);
}
@Test
public void testIterator() {
SimpleClass lhs = new SimpleClass(true);
SimpleClass rhs = new SimpleClass(false);
List<Diff<?>> diffs = lhs.diff(rhs).getDiffs();
Iterator<Diff<?>> expectedIterator = diffs.iterator();
DiffList list = new DiffList(lhs, rhs, diffs, SHORT_STYLE);
Iterator<Diff<?>> iterator = list.iterator();
while (iterator.hasNext()) {
assertTrue(expectedIterator.hasNext());
assertEquals(expectedIterator.next(), iterator.next());
}
}
@Test
public void testToStringOutput() {
DiffList list = new DiffBuilder(new EmptyClass(), new EmptyClass(),
ToStringStyle.SHORT_PREFIX_STYLE).append("test", false, true)
.build();
assertEquals(
"DiffListTest.EmptyClass[test=false] differs from DiffListTest.EmptyClass[test=true]",
list.toString());
}
@Test
public void testToStringSpecifyStyleOutput() {
DiffList list = SIMPLE_FALSE.diff(SIMPLE_TRUE);
assertTrue(list.getToStringStyle().equals(SHORT_STYLE));
String lhsString = new ToStringBuilder(SIMPLE_FALSE,
ToStringStyle.MULTI_LINE_STYLE).append(
SimpleClass.getFieldName(), SIMPLE_FALSE.booleanField).build();
String rhsString = new ToStringBuilder(SIMPLE_TRUE,
ToStringStyle.MULTI_LINE_STYLE).append(
SimpleClass.getFieldName(), SIMPLE_TRUE.booleanField).build();
String expectedOutput = String.format("%s differs from %s", lhsString,
rhsString);
assertEquals(expectedOutput,
list.toString(ToStringStyle.MULTI_LINE_STYLE));
}
@Test(expected = IllegalArgumentException.class)
public void testNullLhs() {
new DiffList(null, SIMPLE_FALSE, SIMPLE_TRUE.diff(SIMPLE_FALSE)
.getDiffs(), SHORT_STYLE);
}
@Test(expected = IllegalArgumentException.class)
public void testNullRhs() {
new DiffList(SIMPLE_TRUE, null, SIMPLE_TRUE.diff(SIMPLE_FALSE)
.getDiffs(), SHORT_STYLE);
}
@Test(expected = IllegalArgumentException.class)
public void testNullList() {
new DiffList(SIMPLE_TRUE, SIMPLE_FALSE, null, SHORT_STYLE);
}
@Test
public void testNullStyle() {
DiffList diffList = new DiffList(SIMPLE_TRUE, SIMPLE_FALSE, SIMPLE_TRUE
.diff(SIMPLE_FALSE).getDiffs(), null);
assertEquals(ToStringStyle.DEFAULT_STYLE, diffList.getToStringStyle());
}
@Test
public void testNoDifferencesString() {
DiffList diffList = new DiffBuilder(SIMPLE_TRUE, SIMPLE_TRUE,
SHORT_STYLE).build();
assertEquals(DiffList.OBJECTS_SAME_STRING, diffList.toString());
}
}

View File

@ -0,0 +1,72 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang3.builder;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
/**
* Unit tests {@link Diff}.
*
* @version $Id$
*/
public class DiffTest {
private static final String FIELD_NAME = "field";
private static final Diff<Boolean> booleanDiff = new BooleanDiff(FIELD_NAME);
private static class BooleanDiff extends Diff<Boolean> {
private static final long serialVersionUID = 1L;
protected BooleanDiff(String fieldName) {
super(fieldName);
}
@Override
public Boolean getLeft() {
return Boolean.TRUE;
}
@Override
public Boolean getRight() {
return Boolean.FALSE;
}
}
@Test(expected = UnsupportedOperationException.class)
public void testCannotModify() {
booleanDiff.setValue(Boolean.FALSE);
}
@Test
public void testGetFieldName() {
assertEquals(FIELD_NAME, booleanDiff.getFieldName());
}
@Test
public void testGetType() {
assertEquals(Boolean.class, booleanDiff.getType());
}
@Test
public void testToString() {
assertEquals(String.format("[%s: %s, %s]", FIELD_NAME, booleanDiff.getLeft(),
booleanDiff.getRight()), booleanDiff.toString());
}
}