001 /*******************************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *******************************************************************************/
019 package org.apache.commons.convert;
020
021 import java.lang.reflect.Array;
022 import java.lang.reflect.Modifier;
023 import java.util.ArrayList;
024 import java.util.Arrays;
025 import java.util.Collection;
026 import java.util.Iterator;
027 import java.util.List;
028 import java.util.Map;
029 import java.util.HashSet;
030 import java.util.Set;
031
032 /** Collection <code>Converter</code> classes. */
033 public class CollectionConverters implements ConverterLoader {
034
035 @SuppressWarnings("unchecked")
036 public void loadConverters() {
037 Converters.loadContainedConverters(CollectionConverters.class);
038 Converters.registerConverter(new GenericToStringConverter<Collection>(Collection.class));
039 Converters.registerConverter(new GenericSingletonToList<Map>(Map.class));
040 Converters.registerConverter(new GenericSingletonToSet<Map>(Map.class));
041 }
042
043 private static class ArrayClassToArrayList<S, T> extends AbstractConverter<S, T> {
044 public ArrayClassToArrayList(Class<S> sourceClass, Class<T> targetClass) {
045 super(sourceClass, targetClass);
046 }
047
048 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
049 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
050 }
051
052 public T convert(S obj) throws ConversionException {
053 List<Object> list = new ArrayList<Object>();
054 int len = Array.getLength(obj);
055 for (int i = 0; i < len; i++) {
056 list.add(Array.get(obj, i));
057 }
058 return Util.<T>cast(list);
059 }
060 }
061
062 private static class ArrayClassToHashSet<S, T> extends AbstractConverter<S, T> {
063 public ArrayClassToHashSet(Class<S> sourceClass, Class<T> targetClass) {
064 super(sourceClass, targetClass);
065 }
066
067 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
068 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
069 }
070
071 public T convert(S obj) throws ConversionException {
072 Set<Object> set = new HashSet<Object>();
073 int len = Array.getLength(obj);
074 for (int i = 0; i < len; i++) {
075 set.add(Array.get(obj, i));
076 }
077 return Util.<T>cast(set);
078 }
079 }
080
081 private static class ArrayClassToList<S, T> extends AbstractConverter<S, T> {
082 public ArrayClassToList(Class<S> sourceClass, Class<T> targetClass) {
083 super(sourceClass, targetClass);
084 }
085
086 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
087 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
088 }
089
090 @SuppressWarnings("unchecked")
091 public T convert(S obj) throws ConversionException {
092 List<Object> list = null;
093 try {
094 list = (List<Object>) this.getTargetClass().newInstance();
095 } catch (Exception e) {
096 throw new ConversionException(e);
097 }
098 int len = Array.getLength(obj);
099 for (int i = 0; i < len; i++) {
100 list.add(Array.get(obj, i));
101 }
102 return Util.<T>cast(list);
103 }
104 }
105
106 private static class ArrayClassToSet<S, T> extends AbstractConverter<S, T> {
107 public ArrayClassToSet(Class<S> sourceClass, Class<T> targetClass) {
108 super(sourceClass, targetClass);
109 }
110
111 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
112 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
113 }
114
115 @SuppressWarnings("unchecked")
116 public T convert(S obj) throws ConversionException {
117 Set<Object> set = new HashSet<Object>();
118 try {
119 set = (Set<Object>) this.getTargetClass().newInstance();
120 } catch (Exception e) {
121 throw new ConversionException(e);
122 }
123 int len = Array.getLength(obj);
124 for (int i = 0; i < len; i++) {
125 set.add(Array.get(obj, i));
126 }
127 return Util.<T>cast(set);
128 }
129 }
130
131 public static class ArrayCreator implements ConverterCreator, ConverterLoader {
132 @SuppressWarnings("unchecked")
133 public <S, T> Converter<S, T> createConverter(Class<S> sourceClass, Class<T> targetClass) {
134 if (!targetClass.isArray()) {
135 return null;
136 }
137 if (!Collection.class.isAssignableFrom(sourceClass)) {
138 return null;
139 }
140 if (targetClass.getComponentType() == Boolean.TYPE) {
141 return Util.cast(new CollectionToBooleanArray(sourceClass, targetClass));
142 }
143 if (targetClass.getComponentType() == Byte.TYPE) {
144 return Util.cast(new CollectionToByteArray(sourceClass, targetClass));
145 }
146 if (targetClass.getComponentType() == Character.TYPE) {
147 return Util.cast(new CollectionToCharArray(sourceClass, targetClass));
148 }
149 if (targetClass.getComponentType() == Double.TYPE) {
150 return Util.cast(new CollectionToDoubleArray(sourceClass, targetClass));
151 }
152 if (targetClass.getComponentType() == Float.TYPE) {
153 return Util.cast(new CollectionToFloatArray(sourceClass, targetClass));
154 }
155 if (targetClass.getComponentType() == Integer.TYPE) {
156 return Util.cast(new CollectionToIntArray(sourceClass, targetClass));
157 }
158 if (targetClass.getComponentType() == Long.TYPE) {
159 return Util.cast(new CollectionToLongArray(sourceClass, targetClass));
160 }
161 if (targetClass.getComponentType() == Short.TYPE) {
162 return Util.cast(new CollectionToShortArray(sourceClass, targetClass));
163 }
164 return Util.cast(new CollectionToObjectArray(sourceClass, targetClass));
165 }
166
167 public void loadConverters() {
168 Converters.registerCreator(this);
169 }
170 }
171
172 /**
173 * An object that converts an array to a <code>List</code>.
174 */
175 public static class ArrayToList<T> extends AbstractConverter<T[], List<T>> {
176 public ArrayToList() {
177 super(Object[].class, List.class);
178 }
179
180 @Override
181 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
182 if (!sourceClass.isArray()) {
183 return false;
184 }
185 if (!List.class.isAssignableFrom(targetClass)) {
186 return false;
187 }
188 if (Object[].class.isAssignableFrom(sourceClass)) {
189 return true;
190 }
191 return false;
192 }
193
194 /**
195 * Returns a <code>List</code> that contains the elements in
196 * <code>obj</code>.
197 */
198 public List<T> convert(T[] obj) throws ConversionException {
199 return Arrays.asList(obj);
200 }
201 }
202
203 @SuppressWarnings("unchecked")
204 private static class CollectionToBooleanArray<T> extends AbstractConverter<Collection, T> {
205 public CollectionToBooleanArray(Class<Collection> sourceClass, Class<T> targetClass) {
206 super(sourceClass, targetClass);
207 }
208
209 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
210 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
211 }
212
213 public T convert(Collection obj) throws ConversionException {
214 boolean[] array = new boolean[obj.size()];
215 int index = 0;
216 Iterator<Boolean> iterator = obj.iterator();
217 while (iterator.hasNext()) {
218 array[index] = iterator.next().booleanValue();
219 index++;
220 }
221 return Util.<T>cast(array);
222 }
223 }
224
225 @SuppressWarnings("unchecked")
226 private static class CollectionToByteArray<T> extends AbstractConverter<Collection, T> {
227 public CollectionToByteArray(Class<Collection> sourceClass, Class<T> targetClass) {
228 super(sourceClass, targetClass);
229 }
230
231 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
232 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
233 }
234
235 public T convert(Collection obj) throws ConversionException {
236 byte[] array = new byte[obj.size()];
237 int index = 0;
238 Iterator<Byte> iterator = obj.iterator();
239 while (iterator.hasNext()) {
240 array[index] = iterator.next().byteValue();
241 index++;
242 }
243 return Util.<T>cast(array);
244 }
245 }
246
247 @SuppressWarnings("unchecked")
248 private static class CollectionToCharArray<T> extends AbstractConverter<Collection, T> {
249 public CollectionToCharArray(Class<Collection> sourceClass, Class<T> targetClass) {
250 super(sourceClass, targetClass);
251 }
252
253 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
254 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
255 }
256
257 public T convert(Collection obj) throws ConversionException {
258 char[] array = new char[obj.size()];
259 int index = 0;
260 Iterator<Character> iterator = obj.iterator();
261 while (iterator.hasNext()) {
262 array[index] = iterator.next().charValue();
263 index++;
264 }
265 return Util.<T>cast(array);
266 }
267 }
268
269 @SuppressWarnings("unchecked")
270 private static class CollectionToDoubleArray<T> extends AbstractConverter<Collection, T> {
271 public CollectionToDoubleArray(Class<Collection> sourceClass, Class<T> targetClass) {
272 super(sourceClass, targetClass);
273 }
274
275 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
276 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
277 }
278
279 public T convert(Collection obj) throws ConversionException {
280 double[] array = new double[obj.size()];
281 int index = 0;
282 Iterator<Double> iterator = obj.iterator();
283 while (iterator.hasNext()) {
284 array[index] = iterator.next().doubleValue();
285 index++;
286 }
287 return Util.<T>cast(array);
288 }
289 }
290
291 @SuppressWarnings("unchecked")
292 private static class CollectionToFloatArray<T> extends AbstractConverter<Collection, T> {
293 public CollectionToFloatArray(Class<Collection> sourceClass, Class<T> targetClass) {
294 super(sourceClass, targetClass);
295 }
296
297 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
298 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
299 }
300
301 public T convert(Collection obj) throws ConversionException {
302 float[] array = new float[obj.size()];
303 int index = 0;
304 Iterator<Float> iterator = obj.iterator();
305 while (iterator.hasNext()) {
306 array[index] = iterator.next().floatValue();
307 index++;
308 }
309 return Util.<T>cast(array);
310 }
311 }
312
313 @SuppressWarnings("unchecked")
314 private static class CollectionToIntArray<T> extends AbstractConverter<Collection, T> {
315 public CollectionToIntArray(Class<Collection> sourceClass, Class<T> targetClass) {
316 super(sourceClass, targetClass);
317 }
318
319 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
320 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
321 }
322
323 public T convert(Collection obj) throws ConversionException {
324 int[] array = new int[obj.size()];
325 int index = 0;
326 Iterator<Integer> iterator = obj.iterator();
327 while (iterator.hasNext()) {
328 array[index] = iterator.next().intValue();
329 index++;
330 }
331 return Util.<T>cast(array);
332 }
333 }
334
335 @SuppressWarnings("unchecked")
336 private static class CollectionToLongArray<T> extends AbstractConverter<Collection, T> {
337 public CollectionToLongArray(Class<Collection> sourceClass, Class<T> targetClass) {
338 super(sourceClass, targetClass);
339 }
340
341 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
342 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
343 }
344
345 public T convert(Collection obj) throws ConversionException {
346 long[] array = new long[obj.size()];
347 int index = 0;
348 Iterator<Long> iterator = obj.iterator();
349 while (iterator.hasNext()) {
350 array[index] = iterator.next().longValue();
351 index++;
352 }
353 return Util.<T>cast(array);
354 }
355 }
356
357 @SuppressWarnings("unchecked")
358 private static class CollectionToObjectArray<T> extends AbstractConverter<Collection, T> {
359 public CollectionToObjectArray(Class<Collection> sourceClass, Class<T> targetClass) {
360 super(sourceClass, targetClass);
361 }
362
363 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
364 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
365 }
366
367 public T convert(Collection obj) throws ConversionException {
368 return Util.<T>cast(obj.toArray());
369 }
370 }
371
372 @SuppressWarnings("unchecked")
373 private static class CollectionToShortArray<T> extends AbstractConverter<Collection, T> {
374 public CollectionToShortArray(Class<Collection> sourceClass, Class<T> targetClass) {
375 super(sourceClass, targetClass);
376 }
377
378 public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
379 return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
380 }
381
382 public T convert(Collection obj) throws ConversionException {
383 short[] array = new short[obj.size()];
384 int index = 0;
385 Iterator<Short> iterator = obj.iterator();
386 while (iterator.hasNext()) {
387 array[index] = iterator.next().shortValue();
388 index++;
389 }
390 return Util.<T>cast(array);
391 }
392 }
393
394 public static class ListCreator implements ConverterCreator, ConverterLoader {
395 public <S, T> Converter<S, T> createConverter(Class<S> sourceClass, Class<T> targetClass) {
396 if (!sourceClass.isArray()) {
397 return null;
398 }
399 if (!List.class.isAssignableFrom(targetClass)) {
400 return null;
401 }
402 if (!(sourceClass.getComponentType() instanceof Object)) {
403 return null;
404 }
405 if ((targetClass.getModifiers() & Modifier.ABSTRACT) == 0) {
406 return Util.cast(new ArrayClassToList<S, T>(sourceClass, targetClass));
407 } else {
408 return Util.cast(new ArrayClassToArrayList<S, T>(sourceClass, targetClass));
409 }
410 }
411
412 public void loadConverters() {
413 Converters.registerCreator(this);
414 }
415 }
416
417 public static class SetCreator implements ConverterCreator, ConverterLoader {
418 public <S, T> Converter<S, T> createConverter(Class<S> sourceClass, Class<T> targetClass) {
419 if (!sourceClass.isArray()) {
420 return null;
421 }
422 if (!Set.class.isAssignableFrom(targetClass)) {
423 return null;
424 }
425 if (!(sourceClass.getComponentType() instanceof Object)) {
426 return null;
427 }
428 if ((targetClass.getModifiers() & Modifier.ABSTRACT) == 0) {
429 return Util.cast(new ArrayClassToSet<S, T>(sourceClass, targetClass));
430 } else {
431 return Util.cast(new ArrayClassToHashSet<S, T>(sourceClass, targetClass));
432 }
433 }
434
435 public void loadConverters() {
436 Converters.registerCreator(this);
437 }
438 }
439 }