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.Array;
024import java.lang.reflect.Type;
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 Array2Collection extends Converter {
037
038    public Array2Collection(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.getClass().isArray())
053            return false;
054
055        Class<?> oComponentClass = value.getClass().getComponentType();
056        if (targetComponentType.equals(oComponentClass))
057            return true;
058
059        Converter itemConverter = null;
060        final int length = Array.getLength(value);
061        for (int i = 0; i < length; i++) {
062            Object item = Array.get(value, i);
063
064            if (itemConverter == null)
065                itemConverter = converters.getConverter(item, targetComponentType);
066            else if (!itemConverter.canConvert(item, targetComponentType))
067                itemConverter = converters.getConverter(item, targetComponentType);
068
069            if (itemConverter == null)
070                return false;
071        }
072
073        return true;
074    }
075
076    @Override
077        protected Object internalConvert(Object value, Type targetType) {
078
079        if (value == null)
080            return null;
081
082        if (value.getClass().isArray()) {
083            Type targetComponentType = CollectionUtil.getComponentType(targetType);
084
085            if (targetComponentType != null) {
086                final int length = Array.getLength(value);
087                Class<?> targetClass = TypeUtil.classOfType(targetType);
088
089                Collection<Object> targetInstance = null;
090                try {
091                    targetInstance = CollectionUtil.newCollection(targetClass, Array.getLength(value));
092                } catch (Exception e) {
093                    throw new IllegalConverterArgumentException(this, value, targetType, e);
094                }
095
096                Converter itemConverter = null;
097                for (int i = 0; i < length; i++) {
098                    Object item = Array.get(value, i);
099
100                    if (itemConverter == null)
101                        itemConverter = converters.getConverter(item, targetComponentType);
102                    else if (!itemConverter.canConvert(item, targetComponentType))
103                        itemConverter = converters.getConverter(item, targetComponentType);
104
105                    if (itemConverter == null)
106                        throw new IllegalConverterArgumentException(this, value, targetType);
107
108                    targetInstance.add(itemConverter.convert(item, targetComponentType));
109                }
110
111                return targetInstance;
112            }
113        }
114
115        throw new IllegalConverterArgumentException(this, value, targetType);
116    }
117}