1 package com.github.mygreen.supercsv.cellprocessor.constraint;
2
3 import java.util.HashMap;
4 import java.util.Map;
5
6 import org.supercsv.cellprocessor.ift.CellProcessor;
7 import org.supercsv.util.CsvContext;
8
9 import com.github.mygreen.supercsv.cellprocessor.ValidationCellProcessor;
10 import com.github.mygreen.supercsv.cellprocessor.format.TextPrinter;
11
12
13
14
15
16
17
18
19 public class Unique<T> extends ValidationCellProcessor {
20
21 private final Map<T, ValueObject> encounteredElements = new HashMap<>();
22
23 private final TextPrinter<T> printer;
24
25 public Unique(final TextPrinter<T> printer) {
26 super();
27 checkPreconditions(printer);
28 this.printer = printer;
29 }
30
31 public Unique(final TextPrinter<T> printer, final CellProcessor next) {
32 super(next);
33 checkPreconditions(printer);
34 this.printer = printer;
35 }
36
37 private static <T> void checkPreconditions(final TextPrinter<T> printer) {
38 if(printer == null) {
39 throw new NullPointerException("printer should not be null.");
40 }
41 }
42
43 @SuppressWarnings("unchecked")
44 @Override
45 public Object execute(final Object value, final CsvContext context) {
46
47 if(value == null) {
48 return next.execute(value, context);
49 }
50
51 final T result = (T)value;
52
53 if(encounteredElements.containsKey(result)) {
54
55 final String formattedValue = printer.print(result);
56 final ValueObject duplicatedObject = encounteredElements.get(result);
57 throw createValidationException(context)
58 .messageFormat("duplicate value '%s' encountered.", formattedValue)
59 .rejectedValue(result)
60 .messageVariables("duplicatedLineNumber", duplicatedObject.lineNumber)
61 .messageVariables("duplicatedRowNumber", duplicatedObject.rowNumber)
62 .messageVariables("printer", getPrinter())
63 .build();
64
65 } else {
66 final ValueObject object = new ValueObject(result, context.getLineNumber(), context.getRowNumber());
67 encounteredElements.put(object.value, object);
68 }
69
70 return next.execute(value, context);
71 }
72
73 private class ValueObject {
74
75 final T value;
76
77 final int lineNumber;
78
79 final int rowNumber;
80
81
82 ValueObject(final T value, final int lineNumber, final int rowNumber) {
83 this.value = value;
84 this.lineNumber = lineNumber;
85 this.rowNumber = rowNumber;
86 }
87 }
88
89
90
91
92
93 public TextPrinter<T> getPrinter() {
94 return printer;
95 }
96
97 }