1 16 package org.springframework.binding.convert.support; 17 18 import java.util.Arrays ; 19 import java.util.Collections ; 20 import java.util.HashMap ; 21 import java.util.HashSet ; 22 import java.util.Iterator ; 23 import java.util.LinkedList ; 24 import java.util.Map ; 25 import java.util.Set ; 26 27 import org.springframework.binding.convert.ConversionExecutor; 28 import org.springframework.binding.convert.ConversionService; 29 import org.springframework.binding.convert.Converter; 30 import org.springframework.util.Assert; 31 import org.springframework.util.ClassUtils; 32 import org.springframework.util.StringUtils; 33 34 39 public class GenericConversionService implements ConversionService { 40 41 47 private Map sourceClassConverters = new HashMap (); 48 49 53 private Map aliasMap = new HashMap (); 54 55 58 private ConversionService parent; 59 60 public void setParent(ConversionService parent) { 61 this.parent = parent; 62 } 63 64 public void addConverter(Converter converter) { 65 Class [] sourceClasses = converter.getSourceClasses(); 66 Class [] targetClasses = converter.getTargetClasses(); 67 for (int i = 0; i < sourceClasses.length; i++) { 68 Class sourceClass = sourceClasses[i]; 69 Map sourceMap = (Map )sourceClassConverters.get(sourceClass); 70 if (sourceMap == null) { 71 sourceMap = new HashMap (); 72 sourceClassConverters.put(sourceClass, sourceMap); 73 } 74 for (int j = 0; j < targetClasses.length; j++) { 75 Class targetClass = targetClasses[j]; 76 sourceMap.put(targetClass, converter); 77 } 78 } 79 if (converter instanceof ConversionServiceAware) { 80 ((ConversionServiceAware)converter).setConversionService(this); 81 } 82 } 83 84 public void addConverter(Converter converter, String alias) { 85 aliasMap.put(alias, converter); 86 addConverter(converter); 87 } 88 89 public void addConverters(Converter[] converters) { 90 for (int i = 0; i < converters.length; i++) { 91 addConverter(converters[i]); 92 } 93 } 94 95 public void addAlias(String alias, Class targetType) { 96 aliasMap.put(alias, targetType); 97 } 98 99 public void addDefaultAlias(Class targetType) { 100 addAlias(StringUtils.uncapitalize(ClassUtils.getShortName(targetType)), targetType); 101 } 102 103 public ConversionExecutor[] getConversionExecutorsForSource(Class sourceClass) { 104 Assert.notNull(sourceClass, "The source class to convert from is required"); 105 Map sourceTargetConverters = findConvertersForSource(sourceClass); 106 if (sourceTargetConverters.isEmpty()) { 107 if (parent != null) { 108 return parent.getConversionExecutorsForSource(sourceClass); 109 } 110 else { 111 return new ConversionExecutor[0]; 112 } 113 } 114 Set executors = new HashSet (); 115 if (parent != null) { 116 executors.addAll(Arrays.asList(parent.getConversionExecutorsForSource(sourceClass))); 117 } 118 Iterator it = sourceTargetConverters.entrySet().iterator(); 119 while (it.hasNext()) { 120 Map.Entry entry = (Map.Entry )it.next(); 121 executors.add(new ConversionExecutor(sourceClass, (Class )entry.getKey(), (Converter)entry.getValue())); 122 } 123 return (ConversionExecutor[])executors.toArray(new ConversionExecutor[executors.size()]); 124 } 125 126 public ConversionExecutor getConversionExecutor(Class sourceClass, Class targetClass) { 127 Assert.notNull(sourceClass, "The source class to convert from is required"); 128 Assert.notNull(targetClass, "The target class to convert to is required"); 129 if (this.sourceClassConverters == null || this.sourceClassConverters.isEmpty()) { 130 throw new IllegalStateException ("No converters have been added to this service's registry"); 131 } 132 if (sourceClass.equals(targetClass)) { 133 return new ConversionExecutor(sourceClass, targetClass, new NoOpConverter(sourceClass, targetClass)); 134 } 135 Map sourceTargetConverters = findConvertersForSource(sourceClass); 136 Converter converter = findTargetConverter(sourceTargetConverters, targetClass); 137 if (converter != null) { 138 return new ConversionExecutor(sourceClass, targetClass, converter); 139 } 140 else { 141 if (parent != null) { 142 return parent.getConversionExecutor(sourceClass, targetClass); 143 } 144 else { 145 throw new IllegalArgumentException ("No converter registered to convert from sourceClass '" 146 + sourceClass + "' to target class '" + targetClass + "'"); 147 } 148 } 149 } 150 151 public ConversionExecutor getConversionExecutorByTargetAlias(Class sourceClass, String alias) 152 throws IllegalArgumentException { 153 Assert.notNull(sourceClass, "The source class to convert from is required"); 154 Assert.hasText(alias, "The target alias is required and must either be a type alias (e.g 'boolean') " 155 + "or a generic converter alias (e.g. 'bean') "); 156 Object targetType = aliasMap.get(alias); 157 if (targetType == null) { 158 if (parent != null) { 159 return parent.getConversionExecutorByTargetAlias(sourceClass, alias); 160 } 161 else { 162 return null; 163 } 164 } 165 else if (targetType instanceof Class ) { 166 return getConversionExecutor(sourceClass, (Class )targetType); 167 } 168 else { 169 Assert.isInstanceOf(Converter.class, targetType, "Not a converter: "); 170 Converter conv = (Converter)targetType; 171 return new ConversionExecutor(sourceClass, Object .class, conv); 172 } 173 } 174 175 public Class getClassByAlias(String alias) { 176 Assert.hasText(alias, "The alias is required and must be a type alias (e.g 'boolean')"); 177 Object clazz = aliasMap.get(alias); 178 if (clazz != null) { 179 Assert.isInstanceOf(Class .class, clazz, "Not a Class alias '" + alias + "': "); 180 return (Class )clazz; 181 } else { 182 if (parent != null) { 183 return parent.getClassByAlias(alias); 185 } else { 186 return null; 188 } 189 } 190 } 191 192 protected Map findConvertersForSource(Class sourceClass) { 193 LinkedList classQueue = new LinkedList (); 194 classQueue.addFirst(sourceClass); 195 while (!classQueue.isEmpty()) { 196 sourceClass = (Class )classQueue.removeLast(); 197 Map sourceTargetConverters = (Map )sourceClassConverters.get(sourceClass); 198 if (sourceTargetConverters != null && !sourceTargetConverters.isEmpty()) { 199 return sourceTargetConverters; 200 } 201 if (!sourceClass.isInterface() && (sourceClass.getSuperclass() != null)) { 202 classQueue.addFirst(sourceClass.getSuperclass()); 203 } 204 Class [] interfaces = sourceClass.getInterfaces(); 206 for (int i = 0; i < interfaces.length; i++) { 207 classQueue.addFirst(interfaces[i]); 208 } 209 } 210 return Collections.EMPTY_MAP; 211 } 212 213 private Converter findTargetConverter(Map sourceTargetConverters, Class targetClass) { 214 LinkedList classQueue = new LinkedList (); 215 classQueue.addFirst(targetClass); 216 while (!classQueue.isEmpty()) { 217 targetClass = (Class )classQueue.removeLast(); 218 Converter converter = (Converter)sourceTargetConverters.get(targetClass); 219 if (converter != null) { 220 return converter; 221 } 222 if (!targetClass.isInterface() && (targetClass.getSuperclass() != null)) { 223 classQueue.addFirst(targetClass.getSuperclass()); 224 } 225 Class [] interfaces = targetClass.getInterfaces(); 227 for (int i = 0; i < interfaces.length; i++) { 228 classQueue.addFirst(interfaces[i]); 229 } 230 } 231 return null; 232 } 233 234 public ConversionService getParent() { 235 return parent; 236 } 237 238 protected Map getSourceClassConverters() { 239 return sourceClassConverters; 240 } 241 242 protected Map getAliasMap() { 243 return aliasMap; 244 } 245 } | Popular Tags |