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    }