Package de.zalando.sprocwrapper.globalobjecttransformer

Source Code of de.zalando.sprocwrapper.globalobjecttransformer.GlobalObjectTransformerLoader

package de.zalando.sprocwrapper.globalobjecttransformer;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.reflections.Reflections;

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.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;

import de.zalando.sprocwrapper.globalobjecttransformer.annotation.GlobalObjectMapper;

import de.zalando.typemapper.core.fieldMapper.ObjectMapper;

public class GlobalObjectTransformerLoader {

    private static final Logger LOG = LoggerFactory.getLogger(GlobalObjectTransformerLoader.class);

    private static final String DEFAULT_NAMESPACE = "de.zalando";

    private static final String GLOBAL_OBJECT_TRANSFORMER_SEARCH_NAMESPACE =
        "global.object.transformer.search.namespace";

    // you need to set the namespace to a valid value like: org.doodlejump
    private static volatile String namespaceToScan = null;
    private static volatile ImmutableMap<Class<?>, ObjectMapper<?>> register;

    public static <T> ObjectMapper<T> getObjectMapperForClass(final Class<T> genericType) throws InstantiationException,
        IllegalAccessException {
        Preconditions.checkNotNull(genericType, "genericType");

        // performance improvement. Volatile field is read only once in the commons scenario.
        ImmutableMap<Class<?>, ObjectMapper<?>> localRegister = register;
        if (localRegister == null) {

            synchronized (GlobalObjectTransformerLoader.class) {
                localRegister = register;
                if (localRegister == null) {
                    register = localRegister = buildMappers();
                }
            }
        }

        return (ObjectMapper<T>) localRegister.get(genericType);
    }

    private static ImmutableMap<Class<?>, ObjectMapper<?>> buildMappers() throws InstantiationException,
        IllegalAccessException {

        final Map<Class<?>, ObjectMapper<?>> mappers = new HashMap<>();

        for (final Class<?> foundGlobalObjectTransformer : findObjectMappers()) {

            if (ObjectMapper.class.isAssignableFrom(foundGlobalObjectTransformer)) {

                final ObjectMapper<?> mapper = (ObjectMapper<?>) foundGlobalObjectTransformer.newInstance();
                final Class<?> valueTransformerReturnType = mapper.getType();

                final ObjectMapper<?> previousMapper = mappers.put(valueTransformerReturnType, mapper);

                if (previousMapper == null) {
                    LOG.debug("Global Object Mapper [{}] for type [{}] registered. ",
                        foundGlobalObjectTransformer.getSimpleName(), valueTransformerReturnType.getSimpleName());
                } else {
                    LOG.error("Found multiple global object mappers for type [{}]. [{}] replaced by [{}]",
                        new Object[] {
                            valueTransformerReturnType, previousMapper.getClass().getSimpleName(),
                            valueTransformerReturnType.getSimpleName()
                        });
                }
            } else {
                LOG.error("Object mapper [{}] should extend [{}]", foundGlobalObjectTransformer.getSimpleName(),
                    ObjectMapper.class.getSimpleName());
            }
        }

        return ImmutableMap.copyOf(mappers);

    }

    private static Set<Class<?>> findObjectMappers() {
        final Predicate<String> filter = new Predicate<String>() {
            @Override
            public boolean apply(final String input) {
                return GlobalObjectMapper.class.getCanonicalName().equals(input);
            }
        };

        final String myNameSpaceToScan = getNameSpace();

        final Reflections reflections = new Reflections(new ConfigurationBuilder().filterInputsBy(
                    new FilterBuilder.Include(FilterBuilder.prefix(myNameSpaceToScan))).setUrls(
                    ClasspathHelper.forPackage(myNameSpaceToScan)).setScanners(new TypeAnnotationsScanner()
                        .filterResultsBy(filter)));
        final Set<Class<?>> objectMapper = reflections.getTypesAnnotatedWith(GlobalObjectMapper.class);

        return objectMapper;
    }

    private static String getNameSpace() {

        String myNameSpaceToScan = namespaceToScan;

        if (myNameSpaceToScan == null) {
            try {
                myNameSpaceToScan = System.getenv(GLOBAL_OBJECT_TRANSFORMER_SEARCH_NAMESPACE);
            } catch (final Exception e) {

                // ignore - e.g. if a security manager exists and permissions are denied.
                LOG.warn("Could not get the value of environment variable: {}. Using: {}",
                    new Object[] {GLOBAL_OBJECT_TRANSFORMER_SEARCH_NAMESPACE, namespaceToScan, e});
            }

            if (myNameSpaceToScan == null) {
                myNameSpaceToScan = DEFAULT_NAMESPACE;
            }
        }

        return myNameSpaceToScan;
    }

    /**
     * Use this static function to set the namespace to scan.
     *
     * @param  newNamespace  the new namespace to be searched for
     *                       {@link de.zalando.sprocwrapper.globalvaluetransformer.annotation.GlobalValueTransformer}
     */
    public static void changeNamespaceToScan(final String newNamespace) {
        namespaceToScan = Preconditions.checkNotNull(newNamespace, "newNamespace");
        register = null;
    }
}
TOP

Related Classes of de.zalando.sprocwrapper.globalobjecttransformer.GlobalObjectTransformerLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.