com.github.erchu.beancp.MapperExecutorSelector.java Source code

Java tutorial

Introduction

Here is the source code for com.github.erchu.beancp.MapperExecutorSelector.java

Source

/*
 * bean-cp
 * Copyright (c) 2014, Rafal Chojnacki, All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.
 */
package com.github.erchu.beancp;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ClassUtils;
import static org.apache.commons.lang3.ObjectUtils.*;
import static org.apache.commons.lang3.Validate.*;

class MapperExecutorSelector {

    static enum MapperExecutorMatchMode {

        ANY, STRICT_DESTINATION
    }

    private MapperExecutorSelector() {
        throw new AssertionError(String.format("Creating an instance of the %s class is not allowed.",
                MapperExecutorSelector.class));
    }

    public static boolean isMapAvailable(final MappingInfo mappingsInfo, final Class sourceClass,
            final Class destinationClass, final Collection<DeclarativeMapImpl<?, ?>> maps,
            final Collection<MapConventionExecutor> mapAnyConventions) {
        notNull(sourceClass, "sourceClass");
        notNull(destinationClass, "destinationClass");
        notNull(maps, "maps");

        if (getBestMatchingDeclarativeMap(sourceClass, destinationClass, maps) != null) {
            return true;
        }

        return mapAnyConventions.stream().anyMatch(i -> i.canMap(mappingsInfo, sourceClass, destinationClass));
    }

    static boolean isConverterAvailable(final MappingInfo mappingsInfo, final Class sourceClass,
            final Class destinationClass, final Collection<Converter<?, ?>> converters) {
        notNull(sourceClass, "sourceClass");
        notNull(destinationClass, "destinationClass");
        notNull(converters, "converters");

        return (getBestMatchingConverter(sourceClass, destinationClass, converters) != null);
    }

    public static Converter<?, ?> getBestMatchingConverter(final Class sourceClass, final Class destinationClass,
            final Collection<Converter<?, ?>> executors) {
        return (Converter<?, ?>) getBestMatchingMappingExecutor(sourceClass, destinationClass, executors,
                MapperExecutorMatchMode.STRICT_DESTINATION);
    }

    public static DeclarativeMapImpl<?, ?> getBestMatchingDeclarativeMap(final Class sourceClass,
            final Class destinationClass, final Collection<DeclarativeMapImpl<?, ?>> executors) {
        return (DeclarativeMapImpl<?, ?>) getBestMatchingMappingExecutor(sourceClass, destinationClass, executors,
                MapperExecutorMatchMode.ANY);
    }

    private static <T extends MappingExecutor<?, ?>> T getBestMatchingMappingExecutor(final Class sourceClass,
            final Class destinationClass, final Collection<T> executors, final MapperExecutorMatchMode matchMode) {
        List<T> validMappers = executors.stream().filter(i -> canBeMapped(sourceClass, i.getSourceClass())
                && canBeMapped(destinationClass, i.getDestinationClass())).collect(Collectors.toList());

        if (validMappers.isEmpty()) {
            return null;
        }

        T mapper;

        if (matchMode == MapperExecutorMatchMode.STRICT_DESTINATION) {
            mapper = firstNonNull(
                    firstOrNull(validMappers,
                            (i -> classEqualsOrWrapper(sourceClass, i.getSourceClass())
                                    && classEqualsOrWrapper(destinationClass, i.getDestinationClass()))),
                    firstOrNull(validMappers,
                            (i -> classEqualsOrWrapper(destinationClass, i.getDestinationClass()))));
        } else {
            mapper = firstNonNull(
                    firstOrNull(validMappers,
                            (i -> classEqualsOrWrapper(sourceClass, i.getSourceClass())
                                    && classEqualsOrWrapper(destinationClass, i.getDestinationClass()))),
                    firstOrNull(validMappers,
                            (i -> classEqualsOrWrapper(destinationClass, i.getDestinationClass()))),
                    firstOrNull(validMappers, (i -> classEqualsOrWrapper(sourceClass, i.getSourceClass()))),
                    validMappers.get(0));
        }

        return mapper;
    }

    /**
     * Returns first value in {@code collection} which is not equal to null and matches filter. If
     * there is not such element then will return null.
     *
     * @param <T> result type.
     * @param collection collection to search in.
     * @param filter filter predicate.
     * @return first value in {@code collection} which is not equal to null and matches filter, if
     * there is not such element then will return null.
     */
    private static <T> T firstOrNull(final Collection<T> collection, final Predicate<T> filter) {
        Optional<T> findFirst = collection.stream().filter(filter).findFirst();

        return (findFirst.isPresent() ? findFirst.get() : null);
    }

    private static boolean canBeMapped(final Class objectClass, final Class supportedClass) {
        return classEqualsOrWrapper(objectClass, supportedClass) || supportedClass.isAssignableFrom(objectClass);
    }

    private static boolean classEqualsOrWrapper(final Class objectClass, final Class supportedClass) {
        if (objectClass.isPrimitive()) {
            Class<?> primitiveTypeWrapper = ClassUtils.primitiveToWrapper(objectClass);

            return objectClass.equals(supportedClass) || primitiveTypeWrapper.equals(supportedClass);
        } else if (supportedClass.isPrimitive()) {
            Class<?> primitiveTypeWrapper = ClassUtils.primitiveToWrapper(supportedClass);

            return objectClass.equals(supportedClass) || objectClass.equals(primitiveTypeWrapper);
        } else {
            return supportedClass.equals(objectClass);
        }
    }
}