View Javadoc
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.CellProcessor;
23  import org.supercsv.cellprocessor.ift.StringCellProcessor;
24  import org.supercsv.exception.SuperCsvCellProcessorException;
25  import org.supercsv.exception.SuperCsvConstraintViolationException;
26  import org.supercsv.util.CsvContext;
27  
28  /**
29   * This processor ensures that the input String has a length equal to any of the supplied lengths. The length
30   * constraints must all be {@code > 0} or an exception is thrown. Lookup time is O(1).
31   * 
32   * @author Kasper B. Graversen
33   * @author Dominique De Vito
34   * @author James Bassett
35   */
36  public class Strlen extends CellProcessorAdaptor implements StringCellProcessor {
37  	
38  	private final Set<Integer> requiredLengths = new HashSet<Integer>();
39  	
40  	/**
41  	 * Constructs a new <tt>Strlen</tt> processor, which ensures that the input String has a length equal to any of the
42  	 * supplied lengths.
43  	 * 
44  	 * @param requiredLengths
45  	 *            one or more required lengths
46  	 * @throws NullPointerException
47  	 *             if requiredLengths is null
48  	 * @throws IllegalArgumentException
49  	 *             if requiredLengths is empty or contains a negative length
50  	 */
51  	public Strlen(final int... requiredLengths) {
52  		super();
53  		checkPreconditions(requiredLengths);
54  		checkAndAddLengths(requiredLengths);
55  	}
56  	
57  	/**
58  	 * Constructs a new <tt>Strlen</tt> processor, which ensures that the input String has a length equal to the
59  	 * supplied length, then calls the next processor in the chain.
60  	 * 
61  	 * @param requiredLength
62  	 *            the required length
63  	 * @param next
64  	 *            the next processor in the chain
65  	 * @throws NullPointerException
66  	 *             if next is null
67  	 * @throws IllegalArgumentException
68  	 *             if requiredLength is negative
69  	 */
70  	public Strlen(final int requiredLength, final CellProcessor next) {
71  		this(new int[] { requiredLength }, next);
72  	}
73  	
74  	/**
75  	 * Constructs a new <tt>Strlen</tt> processor, which ensures that the input String has a length equal to any of the
76  	 * supplied lengths, then calls the next processor in the chain.
77  	 * 
78  	 * @param requiredLengths
79  	 *            one or more required lengths
80  	 * @param next
81  	 *            the next processor in the chain
82  	 * @throws NullPointerException
83  	 *             if requiredLengths or next is null
84  	 * @throws IllegalArgumentException
85  	 *             if requiredLengths is empty or contains a negative length
86  	 */
87  	public Strlen(final int[] requiredLengths, final CellProcessor next) {
88  		super(next);
89  		checkPreconditions(requiredLengths);
90  		checkAndAddLengths(requiredLengths);
91  	}
92  	
93  	/**
94  	 * Checks the preconditions for creating a new Strlen processor.
95  	 * 
96  	 * @param requiredLengths
97  	 *            one or more required lengths
98  	 * @throws NullPointerException
99  	 *             if requiredLengths is null
100 	 * @throws IllegalArgumentException
101 	 *             if requiredLengths is empty
102 	 */
103 	private static void checkPreconditions(final int... requiredLengths) {
104 		if( requiredLengths == null ) {
105 			throw new NullPointerException("requiredLengths should not be null");
106 		} else if( requiredLengths.length == 0 ) {
107 			throw new IllegalArgumentException("requiredLengths should not be empty");
108 		}
109 	}
110 	
111 	/**
112 	 * Adds each required length, ensuring it isn't negative.
113 	 * 
114 	 * @param requiredLengths
115 	 *            one or more required lengths
116 	 * @throws IllegalArgumentException
117 	 *             if a supplied length is negative
118 	 */
119 	private void checkAndAddLengths(final int... requiredLengths) {
120 		for( final int length : requiredLengths ) {
121 			if( length < 0 ) {
122 				throw new IllegalArgumentException(String.format("required length cannot be negative but was %d",
123 					length));
124 			}
125 			this.requiredLengths.add(length);
126 		}
127 	}
128 	
129 	/**
130 	 * {@inheritDoc}
131 	 * 
132 	 * @throws SuperCsvCellProcessorException
133 	 *             if value is null
134 	 * @throws SuperCsvConstraintViolationException
135 	 *             if the length of value isn't one of the required lengths
136 	 */
137 	public Object execute(final Object value, final CsvContext context) {
138 		validateInputNotNull(value, context);
139 		
140 		final String stringValue = value.toString();
141 		final int length = stringValue.length();
142 		if( !requiredLengths.contains(length) ) {
143 			throw new SuperCsvConstraintViolationException(String.format("the length (%d) of value '%s' not any of the required lengths",
144 				length, stringValue), context, this);
145 		}
146 		
147 		return next.execute(value, context);
148 	}
149 	
150 }