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.Map; 026import java.util.Map.Entry; 027 028import org.granite.messaging.amf.io.convert.Converter; 029import org.granite.messaging.amf.io.convert.Converters; 030import org.granite.messaging.amf.io.convert.IllegalConverterArgumentException; 031import org.granite.util.TypeUtil; 032import org.granite.util.MapUtil; 033 034/** 035 * @author Franck WOLFF 036 */ 037public class Map2Map extends Converter { 038 039 public Map2Map(Converters converters) { 040 super(converters); 041 } 042 043 @Override 044 protected boolean internalCanConvert(Object value, Type targetType) { 045 046 Type[] targetComponentTypes = MapUtil.getComponentTypes(targetType); 047 if (targetComponentTypes == null) 048 return false; // not a map. 049 050 if (value == null) 051 return true; 052 053 if (!(value instanceof Map<?, ?>)) 054 return false; 055 056 Type keyType = targetComponentTypes[0]; 057 Type valueType = targetComponentTypes[1]; 058 059 if ((keyType.equals(Object.class) || keyType instanceof WildcardType) && 060 (valueType.equals(Object.class) || valueType instanceof WildcardType)) 061 return true; 062 063 Converter keyConverter = null; 064 Converter valueConverter = null; 065 for (Map.Entry<?, ?> item : ((Map<?, ?>)value).entrySet()) { 066 067 if (keyConverter == null) 068 keyConverter = converters.getConverter(item.getKey(), keyType); 069 else if (!keyConverter.canConvert(item.getKey(), keyType)) 070 keyConverter = converters.getConverter(item.getKey(), keyType); 071 if (keyConverter == null) 072 return false; 073 074 if (valueConverter == null) 075 valueConverter = converters.getConverter(item.getValue(), valueType); 076 else if (!valueConverter.canConvert(item.getValue(), valueType)) 077 valueConverter = converters.getConverter(item.getValue(), valueType); 078 if (valueConverter == null) 079 return false; 080 } 081 082 return true; 083 } 084 085 @Override 086 protected Object internalConvert(Object value, Type targetType) { 087 088 if (value == null) 089 return null; 090 091 if (value instanceof Map<?, ?>) { 092 Map<?, ?> map = (Map<?, ?>)value; 093 094 Type[] targetComponentTypes = MapUtil.getComponentTypes(targetType); 095 if (targetComponentTypes != null) { 096 Type keyType = targetComponentTypes[0]; 097 Type valueType = targetComponentTypes[1]; 098 099 Class<?> targetClass = TypeUtil.classOfType(targetType); 100 if (targetClass.isInstance(value) && 101 (keyType.equals(Object.class) || keyType instanceof WildcardType) && 102 (valueType.equals(Object.class) || valueType instanceof WildcardType)) 103 return value; 104 105 // Check if all keys and values are compatible 106 if (targetClass.isInstance(value)) { 107 Class<?> keyClass = TypeUtil.classOfType(keyType); 108 Class<?> valueClass = TypeUtil.classOfType(valueType); 109 110 boolean compatible = true; 111 for (Entry<?, ?> entry : ((Map<?, ?>)value).entrySet()) { 112 if (!keyClass.isInstance(entry.getKey()) || !valueClass.isInstance(entry.getValue())) { 113 compatible = false; 114 break; 115 } 116 } 117 if (compatible) 118 return value; 119 } 120 121 Map<Object, Object> targetInstance = null; 122 try { 123 targetInstance = MapUtil.newMap(targetClass, map.size()); 124 } catch (Exception e) { 125 throw new IllegalConverterArgumentException(this, value, targetType, e); 126 } 127 128 Converter keyConverter = null; 129 Converter valueConverter = null; 130 for (Map.Entry<?, ?> item : ((Map<?, ?>)value).entrySet()) { 131 132 if (keyConverter == null) 133 keyConverter = converters.getConverter(item.getKey(), keyType); 134 else if (!keyConverter.canConvert(item.getKey(), keyType)) 135 keyConverter = converters.getConverter(item.getKey(), keyType); 136 if (keyConverter == null) 137 throw new IllegalConverterArgumentException(this, value, targetType); 138 139 if (valueConverter == null) 140 valueConverter = converters.getConverter(item.getValue(), valueType); 141 else if (!valueConverter.canConvert(item.getValue(), valueType)) 142 valueConverter = converters.getConverter(item.getValue(), valueType); 143 if (valueConverter == null) 144 throw new IllegalConverterArgumentException(this, value, targetType); 145 146 targetInstance.put( 147 keyConverter.convert(item.getKey(), keyType), 148 valueConverter.convert(item.getValue(), valueType) 149 ); 150 } 151 152 return targetInstance; 153 } 154 } 155 156 throw new IllegalConverterArgumentException(this, value, targetType); 157 } 158}