001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. 004 * 005 * This file is part of the Granite Data Services Platform. 006 * 007 * Granite Data Services is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * Granite Data Services is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 020 * USA, or see <http://www.gnu.org/licenses/>. 021 */ 022package org.granite.messaging.amf.io.convert.impl; 023 024import java.lang.reflect.Type; 025import java.lang.reflect.WildcardType; 026import java.util.Map; 027import java.util.Map.Entry; 028 029import org.granite.messaging.amf.io.convert.Converter; 030import org.granite.messaging.amf.io.convert.Converters; 031import org.granite.messaging.amf.io.convert.IllegalConverterArgumentException; 032import org.granite.util.TypeUtil; 033import org.granite.util.MapUtil; 034 035/** 036 * @author Franck WOLFF 037 */ 038public class Map2Map extends Converter { 039 040 public Map2Map(Converters converters) { 041 super(converters); 042 } 043 044 @Override 045 protected boolean internalCanConvert(Object value, Type targetType) { 046 047 Type[] targetComponentTypes = MapUtil.getComponentTypes(targetType); 048 if (targetComponentTypes == null) 049 return false; // not a map. 050 051 if (value == null) 052 return true; 053 054 if (!(value instanceof Map<?, ?>)) 055 return false; 056 057 Type keyType = targetComponentTypes[0]; 058 Type valueType = targetComponentTypes[1]; 059 060 if ((keyType.equals(Object.class) || keyType instanceof WildcardType) && 061 (valueType.equals(Object.class) || valueType instanceof WildcardType)) 062 return true; 063 064 Converter keyConverter = null; 065 Converter valueConverter = null; 066 for (Map.Entry<?, ?> item : ((Map<?, ?>)value).entrySet()) { 067 068 if (keyConverter == null) 069 keyConverter = converters.getConverter(item.getKey(), keyType); 070 else if (!keyConverter.canConvert(item.getKey(), keyType)) 071 keyConverter = converters.getConverter(item.getKey(), keyType); 072 if (keyConverter == null) 073 return false; 074 075 if (valueConverter == null) 076 valueConverter = converters.getConverter(item.getValue(), valueType); 077 else if (!valueConverter.canConvert(item.getValue(), valueType)) 078 valueConverter = converters.getConverter(item.getValue(), valueType); 079 if (valueConverter == null) 080 return false; 081 } 082 083 return true; 084 } 085 086 @Override 087 protected Object internalConvert(Object value, Type targetType) { 088 089 if (value == null) 090 return null; 091 092 if (value instanceof Map<?, ?>) { 093 Map<?, ?> map = (Map<?, ?>)value; 094 095 Type[] targetComponentTypes = MapUtil.getComponentTypes(targetType); 096 if (targetComponentTypes != null) { 097 Type keyType = targetComponentTypes[0]; 098 Type valueType = targetComponentTypes[1]; 099 100 Class<?> targetClass = TypeUtil.classOfType(targetType); 101 if (targetClass.isInstance(value) && 102 (keyType.equals(Object.class) || keyType instanceof WildcardType) && 103 (valueType.equals(Object.class) || valueType instanceof WildcardType)) 104 return value; 105 106 // Check if all keys and values are compatible 107 if (targetClass.isInstance(value)) { 108 Class<?> keyClass = TypeUtil.classOfType(keyType); 109 Class<?> valueClass = TypeUtil.classOfType(valueType); 110 111 boolean compatible = true; 112 for (Entry<?, ?> entry : ((Map<?, ?>)value).entrySet()) { 113 if (!keyClass.isInstance(entry.getKey()) || !valueClass.isInstance(entry.getValue())) { 114 compatible = false; 115 break; 116 } 117 } 118 if (compatible) 119 return value; 120 } 121 122 Map<Object, Object> targetInstance = null; 123 try { 124 targetInstance = MapUtil.newMap(targetClass, map.size()); 125 } catch (Exception e) { 126 throw new IllegalConverterArgumentException(this, value, targetType, e); 127 } 128 129 Converter keyConverter = null; 130 Converter valueConverter = null; 131 for (Map.Entry<?, ?> item : ((Map<?, ?>)value).entrySet()) { 132 133 if (keyConverter == null) 134 keyConverter = converters.getConverter(item.getKey(), keyType); 135 else if (!keyConverter.canConvert(item.getKey(), keyType)) 136 keyConverter = converters.getConverter(item.getKey(), keyType); 137 if (keyConverter == null) 138 throw new IllegalConverterArgumentException(this, value, targetType); 139 140 if (valueConverter == null) 141 valueConverter = converters.getConverter(item.getValue(), valueType); 142 else if (!valueConverter.canConvert(item.getValue(), valueType)) 143 valueConverter = converters.getConverter(item.getValue(), valueType); 144 if (valueConverter == null) 145 throw new IllegalConverterArgumentException(this, value, targetType); 146 147 targetInstance.put( 148 keyConverter.convert(item.getKey(), keyType), 149 valueConverter.convert(item.getValue(), valueType) 150 ); 151 } 152 153 return targetInstance; 154 } 155 } 156 157 throw new IllegalConverterArgumentException(this, value, targetType); 158 } 159}