package de.zalando.sprocwrapper.globalvaluetransformer;
import java.util.Set;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import de.zalando.sprocwrapper.globalvaluetransformer.annotation.GlobalValueTransformer;
import de.zalando.typemapper.core.ValueTransformer;
import de.zalando.typemapper.core.fieldMapper.GlobalValueTransformerRegistry;
public class GlobalValueTransformerLoader {
private static final String GLOBAL_VALUE_TRANSFORMER_SEARCH_NAMESPACE = "global.value.transformer.search.namespace";
// you need to set the namespace to a valid value like: org.doodlejump
private static String namespaceToScan = "de.zalando";
private static final Logger LOG = LoggerFactory.getLogger(GlobalValueTransformerLoader.class);
private static boolean scannedClasspath = false;
public static synchronized ValueTransformer<?, ?> getValueTransformerForClass(final Class<?> genericType)
throws InstantiationException, IllegalAccessException {
// did we already scanned the classpath for global value transformers?
if (scannedClasspath == false) {
final Predicate<String> filter = new Predicate<String>() {
@Override
public boolean apply(final String input) {
return GlobalValueTransformer.class.getCanonicalName().equals(input);
}
};
// last to get the namespace from the system environment
String myNameSpaceToScan = null;
try {
myNameSpaceToScan = System.getenv(GLOBAL_VALUE_TRANSFORMER_SEARCH_NAMESPACE);
} catch (final Exception e) {
// ignore - e.g. if a security manager exists and permissions are denied.
}
if (Strings.isNullOrEmpty(myNameSpaceToScan)) {
// last to use the given namespace
myNameSpaceToScan = namespaceToScan;
}
if (!Strings.isNullOrEmpty(myNameSpaceToScan)) {
final Reflections reflections = new Reflections(new ConfigurationBuilder().filterInputsBy(
new FilterBuilder.Include(FilterBuilder.prefix(myNameSpaceToScan))).setUrls(
ClasspathHelper.forPackage(myNameSpaceToScan)).setScanners(new TypeAnnotationsScanner()
.filterResultsBy(filter), new SubTypesScanner()));
final Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(
GlobalValueTransformer.class);
for (final Class<?> foundGlobalValueTransformer : typesAnnotatedWith) {
final Class<?> valueTransformerReturnType = ValueTransformerUtils.getUnmarshalFromDbClass(
foundGlobalValueTransformer);
if (valueTransformerReturnType != null) {
GlobalValueTransformerRegistry.register(valueTransformerReturnType,
(ValueTransformer<?, ?>) foundGlobalValueTransformer.newInstance());
LOG.debug("Global Value Transformer [{}] for type [{}] registered. ",
foundGlobalValueTransformer.getSimpleName(), valueTransformerReturnType.getSimpleName());
} else {
LOG.error(
"Could add global transformer [{}] to global registry. Could not find method unmarshalFromDb.",
foundGlobalValueTransformer);
}
}
}
scannedClasspath = true;
}
return GlobalValueTransformerRegistry.getValueTransformerForClass(genericType);
}
/**
* Use this static function to set the namespace to scan.
*
* @param newNamespace the new namespace to be searched for {@link GlobalValueTransformer}
*/
public static void changeNamespaceToScan(final String newNamespace) {
namespaceToScan = newNamespace;
scannedClasspath = false;
}
}