1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.dbunit.assertion;
22
23 import java.util.Arrays;
24
25 import org.dbunit.dataset.Column;
26 import org.dbunit.dataset.ColumnFilterTable;
27 import org.dbunit.dataset.Columns;
28 import org.dbunit.dataset.DataSetException;
29 import org.dbunit.dataset.ITable;
30 import org.dbunit.dataset.ITableMetaData;
31 import org.dbunit.dataset.NoSuchColumnException;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35
36
37
38
39
40
41 public class DefaultFailureHandler implements FailureHandler
42 {
43 private static final Logger logger =
44 LoggerFactory.getLogger(DefaultFailureHandler.class);
45
46 private String[] _additionalColumnInfo;
47
48 private FailureFactory failureFactory = new DefaultFailureFactory();
49
50
51
52
53
54 public DefaultFailureHandler()
55 {
56 }
57
58
59
60
61
62
63
64
65 public DefaultFailureHandler(final Column[] additionalColumnInfo)
66 {
67
68 if (additionalColumnInfo != null)
69 {
70 this._additionalColumnInfo =
71 Columns.getColumnNames(additionalColumnInfo);
72 }
73 }
74
75
76
77
78
79
80
81
82 public DefaultFailureHandler(final String[] additionalColumnInfo)
83 {
84 this._additionalColumnInfo = additionalColumnInfo;
85 }
86
87
88
89
90
91
92 public void setFailureFactory(final FailureFactory failureFactory)
93 {
94 if (failureFactory == null)
95 {
96 throw new NullPointerException(
97 "The parameter 'failureFactory' must not be null");
98 }
99 this.failureFactory = failureFactory;
100 }
101
102 public Error createFailure(final String message, final String expected,
103 final String actual)
104 {
105 return this.failureFactory.createFailure(message, expected, actual);
106 }
107
108 public Error createFailure(final String message)
109 {
110 return this.failureFactory.createFailure(message);
111 }
112
113 public String getAdditionalInfo(final ITable expectedTable,
114 final ITable actualTable, final int row, final String columnName)
115 {
116
117
118 return buildAdditionalColumnInfo(expectedTable, actualTable, row);
119 }
120
121 private String buildAdditionalColumnInfo(final ITable expectedTable,
122 final ITable actualTable, final int rowIndex)
123 {
124 if (logger.isDebugEnabled())
125 {
126 logger.debug(
127 "buildAdditionalColumnInfo(expectedTable={}, actualTable={}, rowIndex={}, "
128 + "additionalColumnInfo={}) - start",
129 expectedTable, actualTable,
130 rowIndex, _additionalColumnInfo);
131 }
132
133
134 if (_additionalColumnInfo == null || _additionalColumnInfo.length <= 0)
135 {
136 return null;
137 }
138
139 final StringBuilder sb = new StringBuilder();
140 sb.append("Additional row info:");
141 for (int j = 0; j < _additionalColumnInfo.length; j++)
142 {
143 final String columnName = _additionalColumnInfo[j];
144
145 final Object expectedKeyValue =
146 getColumnValue(expectedTable, rowIndex, columnName);
147 final Object actualKeyValue =
148 getColumnValue(actualTable, rowIndex, columnName);
149
150 sb.append(" ('");
151 sb.append(columnName);
152 sb.append("': expected=<");
153 sb.append(expectedKeyValue);
154 sb.append(">, actual=<");
155 sb.append(actualKeyValue);
156 sb.append(">)");
157 }
158
159 return sb.toString();
160 }
161
162 protected Object getColumnValue(final ITable table, final int rowIndex,
163 final String columnName)
164 {
165 Object value = null;
166 try
167 {
168
169
170 final ITable tableForCol = getTableForColumn(table, columnName);
171 value = tableForCol.getValue(rowIndex, columnName);
172 } catch (final DataSetException e)
173 {
174 value = makeAdditionalColumnInfoErrorMessage(columnName, e);
175 }
176 return value;
177 }
178
179 protected String makeAdditionalColumnInfoErrorMessage(
180 final String columnName, final DataSetException e)
181 {
182 final StringBuilder sb = new StringBuilder();
183 sb.append("Exception creating more info for column '");
184 sb.append(columnName);
185 sb.append("': ");
186 sb.append(e.getClass().getName());
187 sb.append(": ");
188 sb.append(e.getMessage());
189 final String msg = sb.toString();
190
191 logger.warn(msg, e);
192
193 return " (!!!!! " + msg + ")";
194 }
195
196
197
198
199
200
201
202
203
204
205
206 private ITable getTableForColumn(final ITable table,
207 final String columnName) throws DataSetException
208 {
209 final ITableMetaData tableMetaData = table.getTableMetaData();
210 try
211 {
212 tableMetaData.getColumnIndex(columnName);
213
214
215 return table;
216 } catch (final NoSuchColumnException e)
217 {
218
219 if (table instanceof ColumnFilterTable)
220 {
221 final ITableMetaData originalMetaData =
222 ((ColumnFilterTable) table).getOriginalMetaData();
223 originalMetaData.getColumnIndex(columnName);
224
225
226 return table;
227 } else
228 {
229
230 throw e;
231 }
232 }
233 }
234
235 public void handle(final Difference diff)
236 {
237 final String msg = buildMessage(diff);
238
239 final Error err =
240 this.createFailure(msg, String.valueOf(diff.getExpectedValue()),
241 String.valueOf(diff.getActualValue()));
242
243 throw err;
244 }
245
246 protected String buildMessage(final Difference diff)
247 {
248 final StringBuilder builder = new StringBuilder(200);
249
250 final int rowNum = diff.getRowIndex();
251 final String columnName = diff.getColumnName();
252 final ITable expectedTable = diff.getExpectedTable();
253 final ITable actualTable = diff.getActualTable();
254
255 addFailMessage(diff, builder);
256
257 final String expectedTableName =
258 expectedTable.getTableMetaData().getTableName();
259
260
261
262
263
264 builder.append("value (table=").append(expectedTableName);
265 builder.append(", row=").append(rowNum);
266 builder.append(", col=").append(columnName);
267
268 final String additionalInfo = this.getAdditionalInfo(expectedTable,
269 actualTable, rowNum, columnName);
270 if (additionalInfo != null && !additionalInfo.trim().equals(""))
271 {
272 builder.append(", ").append(additionalInfo);
273 }
274
275 builder.append(")");
276
277 return builder.toString();
278 }
279
280 protected void addFailMessage(final Difference diff,
281 final StringBuilder builder)
282 {
283 final String failMessage = diff.getFailMessage();
284 final boolean isFailMessage = isFailMessage(failMessage);
285 if (isFailMessage)
286 {
287 builder.append(failMessage).append(": ");
288 }
289 }
290
291 protected boolean isFailMessage(final String failMessage)
292 {
293 return failMessage != null && !failMessage.isEmpty();
294 }
295
296 @Override
297 public String toString()
298 {
299 final StringBuilder sb = new StringBuilder();
300 sb.append(DefaultFailureHandler.class.getName()).append("[");
301 sb.append("_additionalColumnInfo=").append(_additionalColumnInfo == null
302 ? "null" : Arrays.asList(_additionalColumnInfo).toString());
303 sb.append("]");
304 return sb.toString();
305 }
306
307
308
309
310
311
312
313
314
315
316
317 public static class DefaultFailureFactory implements FailureFactory
318 {
319 public Error createFailure(final String message, final String expected,
320 final String actual)
321 {
322
323 return new DbComparisonFailure(message, expected, actual);
324 }
325
326 public Error createFailure(final String message)
327 {
328
329 return new DbAssertionFailedError(message);
330 }
331 }
332 }