001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.core; 018 019import java.lang.reflect.Field; 020import java.lang.reflect.Method; 021import java.util.Collection; 022import java.util.Map; 023 024/** 025 * Helper class for determining element types of collections and maps. 026 * 027 * <p>Mainly intended for usage within the framework, determining the 028 * target type of values to be added to a collection or map 029 * (to be able to attempt type conversion if appropriate). 030 * 031 * @author Juergen Hoeller 032 * @author Phillip Webb 033 * @since 2.0 034 * @see ResolvableType 035 * @deprecated as of 4.3.6, in favor of direct {@link ResolvableType} usage 036 */ 037@Deprecated 038public abstract class GenericCollectionTypeResolver { 039 040 /** 041 * Determine the generic element type of the given Collection class 042 * (if it declares one through a generic superclass or generic interface). 043 * @param collectionClass the collection class to introspect 044 * @return the generic type, or {@code null} if none 045 */ 046 @SuppressWarnings("rawtypes") 047 public static Class<?> getCollectionType(Class<? extends Collection> collectionClass) { 048 return ResolvableType.forClass(collectionClass).asCollection().resolveGeneric(); 049 } 050 051 /** 052 * Determine the generic key type of the given Map class 053 * (if it declares one through a generic superclass or generic interface). 054 * @param mapClass the map class to introspect 055 * @return the generic type, or {@code null} if none 056 */ 057 @SuppressWarnings("rawtypes") 058 public static Class<?> getMapKeyType(Class<? extends Map> mapClass) { 059 return ResolvableType.forClass(mapClass).asMap().resolveGeneric(0); 060 } 061 062 /** 063 * Determine the generic value type of the given Map class 064 * (if it declares one through a generic superclass or generic interface). 065 * @param mapClass the map class to introspect 066 * @return the generic type, or {@code null} if none 067 */ 068 @SuppressWarnings("rawtypes") 069 public static Class<?> getMapValueType(Class<? extends Map> mapClass) { 070 return ResolvableType.forClass(mapClass).asMap().resolveGeneric(1); 071 } 072 073 /** 074 * Determine the generic element type of the given Collection field. 075 * @param collectionField the collection field to introspect 076 * @return the generic type, or {@code null} if none 077 */ 078 public static Class<?> getCollectionFieldType(Field collectionField) { 079 return ResolvableType.forField(collectionField).asCollection().resolveGeneric(); 080 } 081 082 /** 083 * Determine the generic element type of the given Collection field. 084 * @param collectionField the collection field to introspect 085 * @param nestingLevel the nesting level of the target type 086 * (typically 1; e.g. in case of a List of Lists, 1 would indicate the 087 * nested List, whereas 2 would indicate the element of the nested List) 088 * @return the generic type, or {@code null} if none 089 */ 090 public static Class<?> getCollectionFieldType(Field collectionField, int nestingLevel) { 091 return ResolvableType.forField(collectionField).getNested(nestingLevel).asCollection().resolveGeneric(); 092 } 093 094 /** 095 * Determine the generic element type of the given Collection field. 096 * @param collectionField the collection field to introspect 097 * @param nestingLevel the nesting level of the target type 098 * (typically 1; e.g. in case of a List of Lists, 1 would indicate the 099 * nested List, whereas 2 would indicate the element of the nested List) 100 * @param typeIndexesPerLevel Map keyed by nesting level, with each value 101 * expressing the type index for traversal at that level 102 * @return the generic type, or {@code null} if none 103 * @deprecated as of 4.0, in favor of using {@link ResolvableType} for arbitrary nesting levels 104 */ 105 @Deprecated 106 public static Class<?> getCollectionFieldType(Field collectionField, int nestingLevel, Map<Integer, Integer> typeIndexesPerLevel) { 107 return ResolvableType.forField(collectionField).getNested(nestingLevel, typeIndexesPerLevel).asCollection().resolveGeneric(); 108 } 109 110 /** 111 * Determine the generic key type of the given Map field. 112 * @param mapField the map field to introspect 113 * @return the generic type, or {@code null} if none 114 */ 115 public static Class<?> getMapKeyFieldType(Field mapField) { 116 return ResolvableType.forField(mapField).asMap().resolveGeneric(0); 117 } 118 119 /** 120 * Determine the generic key type of the given Map field. 121 * @param mapField the map field to introspect 122 * @param nestingLevel the nesting level of the target type 123 * (typically 1; e.g. in case of a List of Lists, 1 would indicate the 124 * nested List, whereas 2 would indicate the element of the nested List) 125 * @return the generic type, or {@code null} if none 126 */ 127 public static Class<?> getMapKeyFieldType(Field mapField, int nestingLevel) { 128 return ResolvableType.forField(mapField).getNested(nestingLevel).asMap().resolveGeneric(0); 129 } 130 131 /** 132 * Determine the generic key type of the given Map field. 133 * @param mapField the map field to introspect 134 * @param nestingLevel the nesting level of the target type 135 * (typically 1; e.g. in case of a List of Lists, 1 would indicate the 136 * nested List, whereas 2 would indicate the element of the nested List) 137 * @param typeIndexesPerLevel Map keyed by nesting level, with each value 138 * expressing the type index for traversal at that level 139 * @return the generic type, or {@code null} if none 140 * @deprecated as of 4.0, in favor of using {@link ResolvableType} for arbitrary nesting levels 141 */ 142 @Deprecated 143 public static Class<?> getMapKeyFieldType(Field mapField, int nestingLevel, Map<Integer, Integer> typeIndexesPerLevel) { 144 return ResolvableType.forField(mapField).getNested(nestingLevel, typeIndexesPerLevel).asMap().resolveGeneric(0); 145 } 146 147 /** 148 * Determine the generic value type of the given Map field. 149 * @param mapField the map field to introspect 150 * @return the generic type, or {@code null} if none 151 */ 152 public static Class<?> getMapValueFieldType(Field mapField) { 153 return ResolvableType.forField(mapField).asMap().resolveGeneric(1); 154 } 155 156 /** 157 * Determine the generic value type of the given Map field. 158 * @param mapField the map field to introspect 159 * @param nestingLevel the nesting level of the target type 160 * (typically 1; e.g. in case of a List of Lists, 1 would indicate the 161 * nested List, whereas 2 would indicate the element of the nested List) 162 * @return the generic type, or {@code null} if none 163 */ 164 public static Class<?> getMapValueFieldType(Field mapField, int nestingLevel) { 165 return ResolvableType.forField(mapField).getNested(nestingLevel).asMap().resolveGeneric(1); 166 } 167 168 /** 169 * Determine the generic value type of the given Map field. 170 * @param mapField the map field to introspect 171 * @param nestingLevel the nesting level of the target type 172 * (typically 1; e.g. in case of a List of Lists, 1 would indicate the 173 * nested List, whereas 2 would indicate the element of the nested List) 174 * @param typeIndexesPerLevel Map keyed by nesting level, with each value 175 * expressing the type index for traversal at that level 176 * @return the generic type, or {@code null} if none 177 * @deprecated as of 4.0, in favor of using {@link ResolvableType} for arbitrary nesting levels 178 */ 179 @Deprecated 180 public static Class<?> getMapValueFieldType(Field mapField, int nestingLevel, Map<Integer, Integer> typeIndexesPerLevel) { 181 return ResolvableType.forField(mapField).getNested(nestingLevel, typeIndexesPerLevel).asMap().resolveGeneric(1); 182 } 183 184 /** 185 * Determine the generic element type of the given Collection parameter. 186 * @param methodParam the method parameter specification 187 * @return the generic type, or {@code null} if none 188 */ 189 public static Class<?> getCollectionParameterType(MethodParameter methodParam) { 190 return ResolvableType.forMethodParameter(methodParam).asCollection().resolveGeneric(); 191 } 192 193 /** 194 * Determine the generic key type of the given Map parameter. 195 * @param methodParam the method parameter specification 196 * @return the generic type, or {@code null} if none 197 */ 198 public static Class<?> getMapKeyParameterType(MethodParameter methodParam) { 199 return ResolvableType.forMethodParameter(methodParam).asMap().resolveGeneric(0); 200 } 201 202 /** 203 * Determine the generic value type of the given Map parameter. 204 * @param methodParam the method parameter specification 205 * @return the generic type, or {@code null} if none 206 */ 207 public static Class<?> getMapValueParameterType(MethodParameter methodParam) { 208 return ResolvableType.forMethodParameter(methodParam).asMap().resolveGeneric(1); 209 } 210 211 /** 212 * Determine the generic element type of the given Collection return type. 213 * @param method the method to check the return type for 214 * @return the generic type, or {@code null} if none 215 */ 216 public static Class<?> getCollectionReturnType(Method method) { 217 return ResolvableType.forMethodReturnType(method).asCollection().resolveGeneric(); 218 } 219 220 /** 221 * Determine the generic element type of the given Collection return type. 222 * <p>If the specified nesting level is higher than 1, the element type of 223 * a nested Collection/Map will be analyzed. 224 * @param method the method to check the return type for 225 * @param nestingLevel the nesting level of the target type 226 * (typically 1; e.g. in case of a List of Lists, 1 would indicate the 227 * nested List, whereas 2 would indicate the element of the nested List) 228 * @return the generic type, or {@code null} if none 229 */ 230 public static Class<?> getCollectionReturnType(Method method, int nestingLevel) { 231 return ResolvableType.forMethodReturnType(method).getNested(nestingLevel).asCollection().resolveGeneric(); 232 } 233 234 /** 235 * Determine the generic key type of the given Map return type. 236 * @param method the method to check the return type for 237 * @return the generic type, or {@code null} if none 238 */ 239 public static Class<?> getMapKeyReturnType(Method method) { 240 return ResolvableType.forMethodReturnType(method).asMap().resolveGeneric(0); 241 } 242 243 /** 244 * Determine the generic key type of the given Map return type. 245 * @param method the method to check the return type for 246 * @param nestingLevel the nesting level of the target type 247 * (typically 1; e.g. in case of a List of Lists, 1 would indicate the 248 * nested List, whereas 2 would indicate the element of the nested List) 249 * @return the generic type, or {@code null} if none 250 */ 251 public static Class<?> getMapKeyReturnType(Method method, int nestingLevel) { 252 return ResolvableType.forMethodReturnType(method).getNested(nestingLevel).asMap().resolveGeneric(0); 253 } 254 255 /** 256 * Determine the generic value type of the given Map return type. 257 * @param method the method to check the return type for 258 * @return the generic type, or {@code null} if none 259 */ 260 public static Class<?> getMapValueReturnType(Method method) { 261 return ResolvableType.forMethodReturnType(method).asMap().resolveGeneric(1); 262 } 263 264 /** 265 * Determine the generic value type of the given Map return type. 266 * @param method the method to check the return type for 267 * @param nestingLevel the nesting level of the target type 268 * (typically 1; e.g. in case of a List of Lists, 1 would indicate the 269 * nested List, whereas 2 would indicate the element of the nested List) 270 * @return the generic type, or {@code null} if none 271 */ 272 public static Class<?> getMapValueReturnType(Method method, int nestingLevel) { 273 return ResolvableType.forMethodReturnType(method).getNested(nestingLevel).asMap().resolveGeneric(1); 274 } 275 276}