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.util;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  import java.util.Map;
21  
22  import org.supercsv.cellprocessor.ift.CellProcessor;
23  import org.supercsv.exception.SuperCsvConstraintViolationException;
24  import org.supercsv.exception.SuperCsvException;
25  
26  /**
27   * Useful utility methods.
28   * 
29   * @author Kasper B. Graversen
30   * @author James Bassett
31   */
32  public final class Util {
33  	
34  	// no instantiation
35  	private Util() {
36  	}
37  	
38  	/**
39  	 * Processes each element in the source List (using the corresponding processor chain in the processors array) and
40  	 * adds it to the destination List. A <tt>null</tt> CellProcessor in the array indicates that no processing is
41  	 * required and the element should be added as-is.
42  	 * 
43  	 * @param destination
44  	 *            the List to add the processed elements to (which is cleared before it's populated)
45  	 * @param source
46  	 *            the List of source elements to be processed
47  	 * @param processors
48  	 *            the array of CellProcessors used to process each element. The number of elements in this array must
49  	 *            match the size of the source List. A <tt>null</tt> CellProcessor in this array indicates that no
50  	 *            processing is required and the element should be added as-is.
51  	 * @param lineNo
52  	 *            the current line number
53  	 * @param rowNo
54  	 *            the current row number
55  	 * @throws NullPointerException
56  	 *             if destination, source or processors is null
57  	 * @throws SuperCsvConstraintViolationException
58  	 *             if a CellProcessor constraint failed
59  	 * @throws SuperCsvException
60  	 *             if source.size() != processors.length, or CellProcessor execution failed
61  	 */
62  	public static void executeCellProcessors(final List<Object> destination, final List<?> source,
63  		final CellProcessor[] processors, final int lineNo, final int rowNo) {
64  		
65  		if( destination == null ) {
66  			throw new NullPointerException("destination should not be null");
67  		} else if( source == null ) {
68  			throw new NullPointerException("source should not be null");
69  		} else if( processors == null ) {
70  			throw new NullPointerException("processors should not be null");
71  		}
72  		
73  		// the context used when cell processors report exceptions
74  		final CsvContext context = new CsvContext(lineNo, rowNo, 1);
75  		context.setRowSource(new ArrayList<Object>(source));
76  		
77  		if( source.size() != processors.length ) {
78  			throw new SuperCsvException(String.format(
79  				"The number of columns to be processed (%d) must match the number of CellProcessors (%d): check that the number"
80  					+ " of CellProcessors you have defined matches the expected number of columns being read/written",
81  				source.size(), processors.length), context);
82  		}
83  		
84  		destination.clear();
85  		
86  		for( int i = 0; i < source.size(); i++ ) {
87  			
88  			context.setColumnNumber(i + 1); // update context (columns start at 1)
89  			
90  			if( processors[i] == null ) {
91  				destination.add(source.get(i)); // no processing required
92  			} else {
93  				destination.add(processors[i].execute(source.get(i), context)); // execute the processor chain
94  			}
95  		}
96  	}
97  	
98  	/**
99  	 * Converts a List to a Map using the elements of the nameMapping array as the keys of the Map.
100 	 * 
101 	 * @param destinationMap
102 	 *            the destination Map (which is cleared before it's populated)
103 	 * @param nameMapping
104 	 *            the keys of the Map (corresponding with the elements in the sourceList). Cannot contain duplicates.
105 	 * @param sourceList
106 	 *            the List to convert
107 	 * @param <T>
108 	 *            the type of the values in the map
109 	 * @throws NullPointerException
110 	 *             if destinationMap, nameMapping or sourceList are null
111 	 * @throws SuperCsvException
112 	 *             if nameMapping and sourceList are not the same size
113 	 */
114 	public static <T> void filterListToMap(final Map<String, T> destinationMap, final String[] nameMapping,
115 		final List<? extends T> sourceList) {
116 		if( destinationMap == null ) {
117 			throw new NullPointerException("destinationMap should not be null");
118 		} else if( nameMapping == null ) {
119 			throw new NullPointerException("nameMapping should not be null");
120 		} else if( sourceList == null ) {
121 			throw new NullPointerException("sourceList should not be null");
122 		} else if( nameMapping.length != sourceList.size() ) {
123 			throw new SuperCsvException(
124 				String
125 					.format(
126 						"the nameMapping array and the sourceList should be the same size (nameMapping length = %d, sourceList size = %d)",
127 						nameMapping.length, sourceList.size()));
128 		}
129 		
130 		destinationMap.clear();
131 		
132 		for( int i = 0; i < nameMapping.length; i++ ) {
133 			final String key = nameMapping[i];
134 			
135 			if( key == null ) {
136 				continue; // null's in the name mapping means skip column
137 			}
138 			
139 			// no duplicates allowed
140 			if( destinationMap.containsKey(key) ) {
141 				throw new SuperCsvException(String.format("duplicate nameMapping '%s' at index %d", key, i));
142 			}
143 			
144 			destinationMap.put(key, sourceList.get(i));
145 		}
146 	}
147 	
148 	/**
149 	 * Returns a List of all of the values in the Map whose key matches an entry in the nameMapping array.
150 	 * 
151 	 * @param map
152 	 *            the map
153 	 * @param nameMapping
154 	 *            the keys of the Map values to add to the List
155 	 * @return a List of all of the values in the Map whose key matches an entry in the nameMapping array
156 	 * @throws NullPointerException
157 	 *             if map or nameMapping is null
158 	 */
159 	public static List<Object> filterMapToList(final Map<String, ?> map, final String[] nameMapping) {
160 		if( map == null ) {
161 			throw new NullPointerException("map should not be null");
162 		} else if( nameMapping == null ) {
163 			throw new NullPointerException("nameMapping should not be null");
164 		}
165 		
166 		final List<Object> result = new ArrayList<Object>(nameMapping.length);
167 		for( final String key : nameMapping ) {
168 			result.add(map.get(key));
169 		}
170 		return result;
171 	}
172 	
173 	/**
174 	 * Converts a Map to an array of objects, adding only those entries whose key is in the nameMapping array.
175 	 * 
176 	 * @param values
177 	 *            the Map of values to convert
178 	 * @param nameMapping
179 	 *            the keys to extract from the Map (elements in the target array will be added in this order)
180 	 * @return the array of Objects
181 	 * @throws NullPointerException
182 	 *             if values or nameMapping is null
183 	 */
184 	public static Object[] filterMapToObjectArray(final Map<String, ?> values, final String[] nameMapping) {
185 		
186 		if( values == null ) {
187 			throw new NullPointerException("values should not be null");
188 		} else if( nameMapping == null ) {
189 			throw new NullPointerException("nameMapping should not be null");
190 		}
191 		
192 		final Object[] targetArray = new Object[nameMapping.length];
193 		int i = 0;
194 		for( final String name : nameMapping ) {
195 			targetArray[i++] = values.get(name);
196 		}
197 		return targetArray;
198 	}
199 	
200 	/**
201 	 * Converts an Object array to a String array (null-safe), by calling toString() on each element.
202 	 * 
203 	 * @param objectArray
204 	 *            the Object array
205 	 * @return the String array, or null if objectArray is null
206 	 */
207 	public static String[] objectArrayToStringArray(final Object[] objectArray) {
208 		if( objectArray == null ) {
209 			return null;
210 		}
211 		
212 		final String[] stringArray = new String[objectArray.length];
213 		for( int i = 0; i < objectArray.length; i++ ) {
214 			stringArray[i] = objectArray[i] != null ? objectArray[i].toString() : null;
215 		}
216 		
217 		return stringArray;
218 	}
219 	
220 	/**
221 	 * Converts an {@code List<Object>} to a String array (null-safe), by calling {@code toString()} on each element.
222 	 * 
223 	 * @param objectList
224 	 *            the List
225 	 * @return the String array, or null if objectList is null
226 	 */
227 	public static String[] objectListToStringArray(final List<?> objectList) {
228 		if( objectList == null ) {
229 			return null;
230 		}
231 		
232 		final String[] stringArray = new String[objectList.size()];
233 		for( int i = 0; i < objectList.size(); i++ ) {
234 			stringArray[i] = objectList.get(i) != null ? objectList.get(i).toString() : null;
235 		}
236 		
237 		return stringArray;
238 	}
239 	
240 }