001/*
002  GRANITE DATA SERVICES
003  Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004
005  This file is part of Granite Data Services.
006
007  Granite Data Services is free software; you can redistribute it and/or modify
008  it under the terms of the GNU Library General Public License as published by
009  the Free Software Foundation; either version 2 of the License, or (at your
010  option) any later version.
011
012  Granite Data Services is distributed in the hope that it will be useful, but
013  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015  for more details.
016
017  You should have received a copy of the GNU Library General Public License
018  along with this library; if not, see <http://www.gnu.org/licenses/>.
019*/
020
021package org.granite.messaging.amf.io.convert.impl;
022
023import java.lang.reflect.Type;
024import java.lang.reflect.WildcardType;
025import java.util.Collection;
026
027import org.granite.messaging.amf.io.convert.Converter;
028import org.granite.messaging.amf.io.convert.Converters;
029import org.granite.messaging.amf.io.convert.IllegalConverterArgumentException;
030import org.granite.util.TypeUtil;
031import org.granite.util.CollectionUtil;
032
033/**
034 * @author Franck WOLFF
035 */
036public class Collection2Collection extends Converter {
037
038    public Collection2Collection(Converters converters) {
039        super(converters);
040    }
041
042    @Override
043        protected boolean internalCanConvert(Object value, Type targetType) {
044
045        Type targetComponentType = CollectionUtil.getComponentType(targetType);
046        if (targetComponentType == null)
047            return false; // not a collection.
048
049        if (value == null)
050            return true;
051
052        if (!(value instanceof Collection<?>))
053            return false;
054
055        if (targetComponentType.equals(Object.class) || targetComponentType instanceof WildcardType)
056            return true;
057
058        Converter itemConverter = null;
059        for (Object item : (Collection<?>)value) {
060
061            if (itemConverter == null)
062                itemConverter = converters.getConverter(item, targetComponentType);
063            else if (!itemConverter.canConvert(item, targetComponentType))
064                itemConverter = converters.getConverter(item, targetComponentType);
065
066            if (itemConverter == null)
067                return false;
068        }
069
070        return true;
071    }
072
073    @Override
074        protected Object internalConvert(Object value, Type targetType) {
075
076        if (value == null)
077            return null;
078
079        if (value instanceof Collection<?>) {
080            Collection<?> c = (Collection<?>)value;
081
082            Type targetComponentType = CollectionUtil.getComponentType(targetType);
083            if (targetComponentType != null) {
084
085                Class<?> targetClass = TypeUtil.classOfType(targetType);
086                if (targetClass.isInstance(value)) {
087                        if (targetComponentType.equals(Object.class) || targetComponentType instanceof WildcardType)
088                                return value;
089                        
090                        if (targetComponentType instanceof Class<?>) {
091                                boolean check = true;
092                                for (Object e : c) {
093                                        if (!((Class<?>)targetComponentType).isInstance(e)) {
094                                                check = false;
095                                                break;
096                                        }
097                                }
098                                if (check)
099                                        return value;
100                        }
101                }
102
103                Collection<Object> targetInstance = null;
104                try {
105                    targetInstance = CollectionUtil.newCollection(targetClass, c.size());
106                } catch (Exception e) {
107                    throw new IllegalConverterArgumentException(this, value, targetType, e);
108                }
109
110                Converter itemConverter = null;
111                for (Object item : c) {
112
113                    if (itemConverter == null)
114                        itemConverter = converters.getConverter(item, targetComponentType);
115                    else if (!itemConverter.canConvert(item, targetComponentType))
116                        itemConverter = converters.getConverter(item, targetComponentType);
117
118                    if (itemConverter == null)
119                        throw new IllegalConverterArgumentException(this, value, targetType);
120
121                    targetInstance.add(itemConverter.convert(item, targetComponentType));
122                }
123
124                return targetInstance;
125            }
126        }
127
128        throw new IllegalConverterArgumentException(this, value, targetType);
129    }
130}