11package org .zalando .sprocwrapper .globalvaluetransformer ;
22
3- import java .lang .reflect .InvocationTargetException ;
4- import java .util .Set ;
5-
3+ import com .google .common .base .Strings ;
64import org .reflections .Reflections ;
7-
85import org .reflections .scanners .SubTypesScanner ;
96import org .reflections .scanners .TypeAnnotationsScanner ;
10-
117import org .reflections .util .ClasspathHelper ;
128import org .reflections .util .ConfigurationBuilder ;
139import org .reflections .util .FilterBuilder ;
14-
1510import org .slf4j .Logger ;
1611import org .slf4j .LoggerFactory ;
17-
18- import com .google .common .base .Predicate ;
19- import com .google .common .base .Strings ;
20-
2112import org .zalando .sprocwrapper .globalvaluetransformer .annotation .GlobalValueTransformer ;
22-
2313import org .zalando .typemapper .core .ValueTransformer ;
2414import org .zalando .typemapper .core .fieldMapper .GlobalValueTransformerRegistry ;
2515
16+ import java .lang .reflect .InvocationTargetException ;
17+ import java .util .Arrays ;
18+ import java .util .HashSet ;
19+ import java .util .Set ;
20+ import java .util .function .Predicate ;
21+ import java .util .stream .Collectors ;
22+
2623public class GlobalValueTransformerLoader {
2724
25+ private static final Logger LOG = LoggerFactory .getLogger (GlobalValueTransformerLoader .class );
2826 private static final String GLOBAL_VALUE_TRANSFORMER_SEARCH_NAMESPACE = "global.value.transformer.search.namespace" ;
29-
30- // you need to set the namespace to a valid value like: org.doodlejump
27+ private static final String NAMESPACE_SEPARATOR = ";" ;
3128 private static String namespaceToScan = "org.zalando" ;
32-
33- private static final Logger LOG = LoggerFactory .getLogger (GlobalValueTransformerLoader .class );
3429 private static boolean scannedClasspath = false ;
3530
3631 public static synchronized ValueTransformer <?, ?> getValueTransformerForClass (final Class <?> genericType )
37- throws InstantiationException , IllegalAccessException , InvocationTargetException , NoSuchMethodException {
32+ throws InstantiationException , IllegalAccessException , InvocationTargetException , NoSuchMethodException {
3833
3934 // did we already scanned the classpath for global value transformers?
40- if (scannedClasspath == false ) {
41- final Predicate <String > filter = new Predicate <String >() {
42- @ Override
43- public boolean apply (final String input ) {
44- return GlobalValueTransformer .class .getCanonicalName ().equals (input );
45- }
46- };
35+ if (!scannedClasspath ) {
4736
4837 // last to get the namespace from the system environment
4938 String myNameSpaceToScan = null ;
@@ -59,29 +48,33 @@ public boolean apply(final String input) {
5948 myNameSpaceToScan = namespaceToScan ;
6049 }
6150
62- if (!Strings .isNullOrEmpty (myNameSpaceToScan )) {
63- final Reflections reflections = new Reflections (new ConfigurationBuilder ().filterInputsBy (
64- new FilterBuilder .Include (FilterBuilder .prefix (myNameSpaceToScan ))).setUrls (
65- ClasspathHelper .forPackage (myNameSpaceToScan )).setScanners (new TypeAnnotationsScanner ()
66- .filterResultsBy (filter ), new SubTypesScanner ()));
67- final Set <Class <?>> typesAnnotatedWith = reflections .getTypesAnnotatedWith (
68- GlobalValueTransformer .class );
69- for (final Class <?> foundGlobalValueTransformer : typesAnnotatedWith ) {
70- final Class <?> valueTransformerReturnType ;
71- try {
72- valueTransformerReturnType = ValueTransformerUtils .getUnmarshalFromDbClass (
73- foundGlobalValueTransformer );
74- GlobalValueTransformerRegistry .register (valueTransformerReturnType ,
75- (ValueTransformer <?, ?>) foundGlobalValueTransformer .getDeclaredConstructor ().newInstance ());
76- } catch (final RuntimeException e ) {
77- LOG .error ("Failed to add global transformer [{}] to global registry." ,
51+ final Set <String > namespaces =
52+ Arrays .stream (myNameSpaceToScan .split (NAMESPACE_SEPARATOR ))
53+ .map (String ::trim )
54+ .filter (Strings ::isNullOrEmpty )
55+ .collect (Collectors .toSet ());
56+
57+ namespaces .add (namespaceToScan );
58+ LOG .debug ("Scan the following packages for {}: {}" , GlobalValueTransformer .class .getSimpleName (),
59+ namespaces );
60+ final Set <Class <?>> typesAnnotatedWith = loadAnnotatedTypes (namespaces );
61+
62+ for (final Class <?> foundGlobalValueTransformer : typesAnnotatedWith ) {
63+ final Class <?> valueTransformerReturnType ;
64+ try {
65+ valueTransformerReturnType = ValueTransformerUtils .getUnmarshalFromDbClass (
66+ foundGlobalValueTransformer );
67+ GlobalValueTransformerRegistry .register (valueTransformerReturnType ,
68+ (ValueTransformer <?, ?>) foundGlobalValueTransformer .getDeclaredConstructor ()
69+ .newInstance ());
70+ } catch (final RuntimeException e ) {
71+ LOG .error ("Failed to add global transformer [{}] to global registry." ,
7872 foundGlobalValueTransformer , e );
79- continue ;
80- }
73+ continue ;
74+ }
8175
82- LOG .debug ("Global Value Transformer [{}] for type [{}] registered. " ,
76+ LOG .debug ("Global Value Transformer [{}] for type [{}] registered." ,
8377 foundGlobalValueTransformer .getSimpleName (), valueTransformerReturnType .getSimpleName ());
84- }
8578 }
8679
8780 scannedClasspath = true ;
@@ -90,10 +83,26 @@ public boolean apply(final String input) {
9083 return GlobalValueTransformerRegistry .getValueTransformerForClass (genericType );
9184 }
9285
86+ private static Set <Class <?>> loadAnnotatedTypes (Set <String > namespacesToScan ) {
87+ final Predicate <String > filter = input -> GlobalValueTransformer .class .getCanonicalName ().equals (input );
88+ final Set <Class <?>> result = new HashSet <>();
89+ for (String namespace : namespacesToScan ) {
90+ final Reflections reflections = new Reflections (
91+ new ConfigurationBuilder ()
92+ .filterInputsBy (new FilterBuilder .Include (FilterBuilder .prefix (namespace )))
93+ .setUrls (ClasspathHelper .forPackage (namespace ))
94+ .setScanners (new TypeAnnotationsScanner ().filterResultsBy (filter ),
95+ new SubTypesScanner ())
96+ );
97+ result .addAll (reflections .getTypesAnnotatedWith (GlobalValueTransformer .class ));
98+ }
99+ return result ;
100+ }
101+
93102 /**
94103 * Use this static function to set the namespace to scan.
95104 *
96- * @param newNamespace the new namespace to be searched for {@link GlobalValueTransformer}
105+ * @param newNamespace the new namespace to be searched for {@link org.zalando.sprocwrapper.globalvaluetransformer.annotation. GlobalValueTransformer}
97106 */
98107 public static void changeNamespaceToScan (final String newNamespace ) {
99108 namespaceToScan = newNamespace ;
0 commit comments