|
package selly.spring.data.convert; |
|
|
|
import java.util.ArrayList; |
|
import java.util.Arrays; |
|
import java.util.Collection; |
|
import java.util.HashMap; |
|
import java.util.List; |
|
import java.util.Map; |
|
|
|
import org.springframework.beans.factory.config.BeanDefinition; |
|
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; |
|
import org.springframework.core.type.filter.AnnotationTypeFilter; |
|
import org.springframework.data.convert.TypeInformationMapper; |
|
import org.springframework.data.util.ClassTypeInformation; |
|
import org.springframework.data.util.TypeInformation; |
|
|
|
/** |
|
* @author Piotr `Athlan` Pelczar |
|
*/ |
|
public class AnnotationTypeInformationMapper implements TypeInformationMapper { |
|
|
|
private final Map<ClassTypeInformation<?>, String> typeToAliasMap; |
|
private final Map<String, ClassTypeInformation<?>> aliasToTypeMap; |
|
|
|
private AnnotationTypeInformationMapper(List<String> basePackagesToScan) { |
|
typeToAliasMap = new HashMap<>(); |
|
aliasToTypeMap = new HashMap<>(); |
|
|
|
populateTypeMap(basePackagesToScan); |
|
} |
|
|
|
private void populateTypeMap(List<String> basePackagesToScan) { |
|
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); |
|
|
|
scanner.addIncludeFilter(new AnnotationTypeFilter(DocumentType.class)); |
|
|
|
for (String basePackage : basePackagesToScan) { |
|
for (BeanDefinition bd : scanner.findCandidateComponents(basePackage)) { |
|
try { |
|
Class<?> clazz = Class.forName(bd.getBeanClassName()); |
|
DocumentType doumentTypeAnnotation = clazz.getAnnotation(DocumentType.class); |
|
|
|
ClassTypeInformation<?> type = ClassTypeInformation.from(clazz); |
|
String alias = doumentTypeAnnotation.value(); |
|
|
|
typeToAliasMap.put(type, alias); |
|
aliasToTypeMap.put(alias, type); |
|
|
|
} catch (ClassNotFoundException e) { |
|
throw new IllegalStateException(String.format("Class [%s] could not be loaded.", bd.getBeanClassName()), e); |
|
} |
|
} |
|
} |
|
} |
|
|
|
/* |
|
* (non-Javadoc) |
|
* @see org.springframework.data.convert.TypeInformationMapper#createAliasFor(org.springframework.data.util.TypeInformation) |
|
*/ |
|
public Object createAliasFor(TypeInformation<?> type) { |
|
ClassTypeInformation<?> typeClass = (ClassTypeInformation<?>) type; |
|
|
|
if(typeToAliasMap.containsKey(typeClass)) { |
|
return typeToAliasMap.get(typeClass); |
|
} |
|
|
|
return null; |
|
} |
|
|
|
/* |
|
* (non-Javadoc) |
|
* @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(java.lang.Object) |
|
*/ |
|
public ClassTypeInformation<?> resolveTypeFrom(Object alias) { |
|
|
|
if(aliasToTypeMap.containsKey(alias)) { |
|
return aliasToTypeMap.get(alias); |
|
} |
|
|
|
return null; |
|
} |
|
|
|
public static class Builder { |
|
List<String> basePackagesToScan; |
|
|
|
public Builder() { |
|
basePackagesToScan = new ArrayList<>(); |
|
} |
|
|
|
public Builder withBasePackage(String basePackage) { |
|
basePackagesToScan.add(basePackage); |
|
return this; |
|
} |
|
|
|
public Builder withBasePackages(String[] basePackages) { |
|
basePackagesToScan.addAll(Arrays.asList(basePackages)); |
|
return this; |
|
} |
|
|
|
public Builder withBasePackages(Collection<? extends String> basePackages) { |
|
basePackagesToScan.addAll(basePackages); |
|
return this; |
|
} |
|
|
|
public AnnotationTypeInformationMapper build() { |
|
AnnotationTypeInformationMapper builded = new AnnotationTypeInformationMapper(basePackagesToScan); |
|
|
|
return builded; |
|
} |
|
} |
|
} |