001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3.builder; 018 019import java.util.Collections; 020import java.util.Iterator; 021import java.util.List; 022 023/** 024 * <p> 025 * A {@code DiffResult} contains a collection of the differences between two 026 * {@link Diffable} objects. Typically these differences are displayed using 027 * {@link #toString()} method, which returns a string describing the fields that 028 * differ between the objects. 029 * </p> 030 * <p> 031 * Use a {@link DiffBuilder} to build a {@code DiffResult} comparing two objects. 032 * </p> 033 * 034 * @since 3.3 035 */ 036public class DiffResult implements Iterable<Diff<?>> { 037 038 /** 039 * <p> 040 * The {@code String} returned when the objects have no differences: 041 * {@value} 042 * </p> 043 */ 044 public static final String OBJECTS_SAME_STRING = ""; 045 046 private static final String DIFFERS_STRING = "differs from"; 047 048 private final List<Diff<?>> diffs; 049 private final Object lhs; 050 private final Object rhs; 051 private final ToStringStyle style; 052 053 /** 054 * <p> 055 * Creates a {@link DiffResult} containing the differences between two 056 * objects. 057 * </p> 058 * 059 * @param lhs 060 * the left hand object 061 * @param rhs 062 * the right hand object 063 * @param diffs 064 * the list of differences, may be empty 065 * @param style 066 * the style to use for the {@link #toString()} method. May be 067 * {@code null}, in which case 068 * {@link ToStringStyle#DEFAULT_STYLE} is used 069 * @throws IllegalArgumentException 070 * if {@code lhs}, {@code rhs} or {@code diffs} is {@code null} 071 */ 072 DiffResult(final Object lhs, final Object rhs, final List<Diff<?>> diffs, 073 final ToStringStyle style) { 074 if (lhs == null) { 075 throw new IllegalArgumentException( 076 "Left hand object cannot be null"); 077 } 078 if (rhs == null) { 079 throw new IllegalArgumentException( 080 "Right hand object cannot be null"); 081 } 082 if (diffs == null) { 083 throw new IllegalArgumentException( 084 "List of differences cannot be null"); 085 } 086 087 this.diffs = diffs; 088 this.lhs = lhs; 089 this.rhs = rhs; 090 091 if (style == null) { 092 this.style = ToStringStyle.DEFAULT_STYLE; 093 } else { 094 this.style = style; 095 } 096 } 097 098 /** 099 * <p> 100 * Returns an unmodifiable list of {@code Diff}s. The list may be empty if 101 * there were no differences between the objects. 102 * </p> 103 * 104 * @return an unmodifiable list of {@code Diff}s 105 */ 106 public List<Diff<?>> getDiffs() { 107 return Collections.unmodifiableList(diffs); 108 } 109 110 /** 111 * <p> 112 * Returns the number of differences between the two objects. 113 * </p> 114 * 115 * @return the number of differences 116 */ 117 public int getNumberOfDiffs() { 118 return diffs.size(); 119 } 120 121 /** 122 * <p> 123 * Returns the style used by the {@link #toString()} method. 124 * </p> 125 * 126 * @return the style 127 */ 128 public ToStringStyle getToStringStyle() { 129 return style; 130 } 131 132 /** 133 * <p> 134 * Builds a {@code String} description of the differences contained within 135 * this {@code DiffResult}. A {@link ToStringBuilder} is used for each object 136 * and the style of the output is governed by the {@code ToStringStyle} 137 * passed to the constructor. 138 * </p> 139 * 140 * <p> 141 * If there are no differences stored in this list, the method will return 142 * {@link #OBJECTS_SAME_STRING}. Otherwise, using the example given in 143 * {@link Diffable} and {@link ToStringStyle#SHORT_PREFIX_STYLE}, an output 144 * might be: 145 * </p> 146 * 147 * <pre> 148 * Person[name=John Doe,age=32] differs from Person[name=Joe Bloggs,age=26] 149 * </pre> 150 * 151 * <p> 152 * This indicates that the objects differ in name and age, but not in 153 * smoking status. 154 * </p> 155 * 156 * <p> 157 * To use a different {@code ToStringStyle} for an instance of this class, 158 * use {@link #toString(ToStringStyle)}. 159 * </p> 160 * 161 * @return a {@code String} description of the differences. 162 */ 163 @Override 164 public String toString() { 165 return toString(style); 166 } 167 168 /** 169 * <p> 170 * Builds a {@code String} description of the differences contained within 171 * this {@code DiffResult}, using the supplied {@code ToStringStyle}. 172 * </p> 173 * 174 * @param style 175 * the {@code ToStringStyle} to use when outputting the objects 176 * 177 * @return a {@code String} description of the differences. 178 */ 179 public String toString(final ToStringStyle style) { 180 if (diffs.size() == 0) { 181 return OBJECTS_SAME_STRING; 182 } 183 184 final ToStringBuilder lhsBuilder = new ToStringBuilder(lhs, style); 185 final ToStringBuilder rhsBuilder = new ToStringBuilder(rhs, style); 186 187 for (final Diff<?> diff : diffs) { 188 lhsBuilder.append(diff.getFieldName(), diff.getLeft()); 189 rhsBuilder.append(diff.getFieldName(), diff.getRight()); 190 } 191 192 return String.format("%s %s %s", lhsBuilder.build(), DIFFERS_STRING, 193 rhsBuilder.build()); 194 } 195 196 /** 197 * <p> 198 * Returns an iterator over the {@code Diff} objects contained in this list. 199 * </p> 200 * 201 * @return the iterator 202 */ 203 @Override 204 public Iterator<Diff<?>> iterator() { 205 return diffs.iterator(); 206 } 207}