1 /*
2 * Copyright 2007 Kasper B. Graversen
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.supercsv.cellprocessor.constraint;
17
18 import java.util.HashSet;
19 import java.util.Set;
20
21 import org.supercsv.cellprocessor.CellProcessorAdaptor;
22 import org.supercsv.cellprocessor.ift.BoolCellProcessor;
23 import org.supercsv.cellprocessor.ift.CellProcessor;
24 import org.supercsv.cellprocessor.ift.DateCellProcessor;
25 import org.supercsv.cellprocessor.ift.DoubleCellProcessor;
26 import org.supercsv.cellprocessor.ift.LongCellProcessor;
27 import org.supercsv.cellprocessor.ift.StringCellProcessor;
28 import org.supercsv.exception.SuperCsvCellProcessorException;
29 import org.supercsv.exception.SuperCsvConstraintViolationException;
30 import org.supercsv.util.CsvContext;
31
32 /**
33 * This processor converts the input to a String, and ensures that the input's hash function matches any of a given set
34 * of hashcodes. Lookup time is O(1).
35 * <p>
36 * This constraint is a very efficient way of ensuring constant expressions are present in certain columns of the CSV
37 * file, such as "BOSS", "EMPLOYEE", or when a column denotes an action to be taken for the input line such as "D"
38 * (delete), "I" (insert), ...
39 * <p>
40 *
41 * @since 1.50
42 * @author Kasper B. Graversen
43 * @author James Bassett
44 */
45 public class RequireHashCode extends CellProcessorAdaptor implements BoolCellProcessor, DateCellProcessor,
46 DoubleCellProcessor, LongCellProcessor, StringCellProcessor {
47
48 private final Set<Integer> requiredHashCodes = new HashSet<Integer>();
49
50 /**
51 * Constructs a new <tt>RequireHashCode</tt> processor, which converts the input to a String, and ensures that the
52 * input's hash function matches any of a given set of hashcodes.
53 *
54 * @param requiredHashcodes
55 * one or more hashcodes
56 * @throws NullPointerException
57 * if requiredHashcodes is null
58 * @throws IllegalArgumentException
59 * if requiredHashcodes is empty
60 */
61 public RequireHashCode(final int... requiredHashcodes) {
62 super();
63 checkPreconditions(requiredHashcodes);
64 for( final int hash : requiredHashcodes ) {
65 this.requiredHashCodes.add(hash);
66 }
67 }
68
69 /**
70 * Constructs a new <tt>RequireHashCode</tt> processor, which converts the input to a String, ensures that the
71 * input's hash function matches the supplied hashcode, then calls the next processor in the chain.
72 *
73 * @param requiredHashcode
74 * the required hashcode
75 * @param next
76 * the next processor in the chain
77 * @throws NullPointerException
78 * if next is null
79 */
80 public RequireHashCode(final int requiredHashcode, final CellProcessor next) {
81 this(new int[] { requiredHashcode }, next);
82 }
83
84 /**
85 * Constructs a new <tt>RequireHashCode</tt> processor, which converts the input to a String, ensures that the
86 * input's hash function matches any of a given set of hashcodes, then calls the next processor in the chain.
87 *
88 * @param requiredHashcodes
89 * one or more hashcodes
90 * @param next
91 * the next processor in the chain
92 * @throws NullPointerException
93 * if requiredHashcodes or next is null
94 * @throws IllegalArgumentException
95 * if requiredHashcodes is empty
96 */
97 public RequireHashCode(final int[] requiredHashcodes, final CellProcessor next) {
98 super(next);
99 checkPreconditions(requiredHashcodes);
100 for( final int hash : requiredHashcodes ) {
101 this.requiredHashCodes.add(hash);
102 }
103 }
104
105 /**
106 * Checks the preconditions for creating a new RequireHashCode processor.
107 *
108 * @param requiredHashcodes
109 * the supplied hashcodes
110 * @throws NullPointerException
111 * if requiredHashcodes is null
112 * @throws IllegalArgumentException
113 * if requiredHashcodes is empty
114 */
115 private static void checkPreconditions(final int... requiredHashcodes) {
116 if( requiredHashcodes == null ) {
117 throw new NullPointerException("requiredHashcodes should not be null");
118 } else if( requiredHashcodes.length == 0 ) {
119 throw new IllegalArgumentException("requiredHashcodes should not be empty");
120 }
121 }
122
123 /**
124 * {@inheritDoc}
125 *
126 * @throws SuperCsvCellProcessorException
127 * if value is null
128 * @throws SuperCsvConstraintViolationException
129 * if value isn't one of the required hash codes
130 */
131 public Object execute(final Object value, final CsvContext context) {
132 validateInputNotNull(value, context);
133
134 int hash = value.hashCode();
135 if( !requiredHashCodes.contains(hash) ) {
136 throw new SuperCsvConstraintViolationException(String.format(
137 "the hashcode of %d for value '%s' does not match any of the required hashcodes", hash, value),
138 context, this);
139 }
140
141 return next.execute(value, context);
142 }
143
144 }