All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.simpleflatmapper.jdbc.DiscriminatorJdbcBuilder Maven / Gradle / Ivy

package org.simpleflatmapper.jdbc;


import org.simpleflatmapper.map.ConsumerErrorHandler;
import org.simpleflatmapper.map.MappingContext;
import org.simpleflatmapper.map.mapper.DiscriminatorMapper;
import org.simpleflatmapper.map.property.FieldMapperColumnDefinition;
import org.simpleflatmapper.util.Enumerable;
import org.simpleflatmapper.util.ErrorHelper;
import org.simpleflatmapper.util.Function;
import org.simpleflatmapper.util.TypeReference;
import org.simpleflatmapper.util.Predicate;
import org.simpleflatmapper.util.UnaryFactory;

import java.lang.reflect.Type;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * The builder is used to build a DiscriminatorMapper that will instantiate
 * different types depending on the value of a specified field.
 * @param  the root type of the jdbcMapper
 */
public class DiscriminatorJdbcBuilder {


    private final String column;
    private final JdbcMapperFactory jdbcMapperFactory;
    private final List builders = new ArrayList();

    public DiscriminatorJdbcBuilder(String column,JdbcMapperFactory jdbcMapperFactory) {
        this.column = column;
        this.jdbcMapperFactory = jdbcMapperFactory;
    }

    /**
     * Add a discriminator value with its associated type.
     * @param value the value
     * @param type the type
     * @return the current builder
     */
    public DiscriminatorJdbcSubBuilder when(String value, Type type) {
        return when(new DiscriminatorPredicate(value), type);
    }

    /**
     * Add a discriminator matching predicate with its associated type.
     * @param predicate the predicate
     * @param type the type
     * @return the current builder
     */
    public DiscriminatorJdbcSubBuilder when(Predicate predicate, Type type) {
        final DiscriminatorJdbcSubBuilder subBuilder = new DiscriminatorJdbcSubBuilder(predicate, type);
        builders.add(subBuilder);
        return subBuilder;
    }

    /**
     * Add a discriminator value with its associated class.
     * @param value the value
     * @param type the class
     * @return the current builder
     */
    public DiscriminatorJdbcSubBuilder when(String value, Class type) {
        return when(value, (Type)type);
    }

    /**
     * Add a discriminator value with its associated type specified by the type reference.
     * @param value the value
     * @param type the type reference
     * @return the current builder
     */
    public DiscriminatorJdbcSubBuilder when(String value, TypeReference type) {
        return when(value, type.getType());
    }

    /**
     *
     * @return a new jdbcMapper based on the current state
     */
    public JdbcMapper mapper() {

        List> mappers =
                new ArrayList>();

        for(DiscriminatorJdbcSubBuilder subBuilder : builders) {
            JdbcSourceFieldMapper mapper = subBuilder.createMapper();
            
            Predicate predicate = new ResultSetDiscriminatorPredicate(column, subBuilder.predicate);
            mappers.add(new DiscriminatorMapper.PredicatedMapper(predicate, mapper, mapper));
        }


        DiscriminatorJdbcMapper discriminatorMapper = new DiscriminatorJdbcMapper(
                mappers,
                new UnaryFactory>() {
                    @Override
                    public Enumerable newInstance(ResultSet resultSet) {
                        return new ResultSetEnumerable(resultSet);
                    }
                },
                new Function() {
                    @Override
                    public String apply(ResultSet in) {
                        try {
                            return column + ":" + in.getObject(column);
                        } catch (SQLException e) {
                            return ErrorHelper.rethrow(e);
                        }
                    }
                },
                jdbcMapperFactory.consumerErrorHandler());
        return discriminatorMapper;
    }


    private static class DiscriminatorJdbcMapper extends DiscriminatorMapper
            implements JdbcMapper {

        public DiscriminatorJdbcMapper(List> predicatedMappers,
                                       UnaryFactory> rowEnumerableFactory,
                                       Function errorConverter,
                                       ConsumerErrorHandler consumerErrorHandler) {
            super(predicatedMappers, rowEnumerableFactory, errorConverter, consumerErrorHandler);
        }

        @Override
        public MappingContext newMappingContext(ResultSet resultSet) throws SQLException {
            return ((JdbcSourceFieldMapper)getMapper(resultSet)).newMappingContext(resultSet);
        }
    }

    private static class DiscriminatorPredicate implements Predicate {
        private final String value;

        private DiscriminatorPredicate(String value) {
            this.value = value;
        }

        @Override
        public boolean test(String discriminatorValue) {
            return value == null ? discriminatorValue == null : value.equals(discriminatorValue);
        }

        @Override
        public String toString() {
            return "DiscriminatorPredicate{value='" + value + '\'' + '}';
        }
    }

    private static class ResultSetDiscriminatorPredicate implements Predicate {
        private final String discriminatorColumn;
        private final Predicate predicate;

        public ResultSetDiscriminatorPredicate(String discriminatorColumn, Predicate predicate) {
            this.discriminatorColumn = discriminatorColumn;
            this.predicate = predicate;
        }

        @Override
        public boolean test(ResultSet resultSet) {
            try {
                return predicate.test(resultSet.getString(discriminatorColumn));
            } catch (SQLException e) {
                return ErrorHelper.rethrow(e);
            }
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            ResultSetDiscriminatorPredicate that = (ResultSetDiscriminatorPredicate) o;

            if (discriminatorColumn != null ? !discriminatorColumn.equals(that.discriminatorColumn) : that.discriminatorColumn != null)
                return false;
            return predicate != null ? predicate.equals(that.predicate) : that.predicate == null;
        }

        @Override
        public int hashCode() {
            int result = discriminatorColumn != null ? discriminatorColumn.hashCode() : 0;
            result = 31 * result + (predicate != null ? predicate.hashCode() : 0);
            return result;
        }
    }

    public class DiscriminatorJdbcSubBuilder {

        private final Type type;
        private final Predicate predicate;
        private JdbcMapperBuilder builder = null;

        public DiscriminatorJdbcSubBuilder(Predicate predicate, Type type) {
            this.type = type;
            this.predicate = predicate;
        }

        /**
         * Static property definition.
         * @see JdbcMapperBuilder
         * @param column the property
         * @return the current builder
         */
        public DiscriminatorJdbcSubBuilder addMapping(String column) {
            return addMapping(column, FieldMapperColumnDefinition.identity());
        }

        /**
         * Static property definition.
         * @see JdbcMapperBuilder
         * @param column the property
         * @param columnDefinition the property definition
         * @return the current builder
         */
        public DiscriminatorJdbcSubBuilder addMapping(String column, FieldMapperColumnDefinition columnDefinition) {
            initBuilder();
            builder.addMapping(column, columnDefinition);
            return this;
        }

        private void initBuilder() {
            if (builder == null) {
                builder = jdbcMapperFactory.newBuilder(type);
            }
        }

        /**
         * Static property definition.
         * @see JdbcMapperBuilder
         * @param column the property
         * @param index the property index
         * @param columnDefinition the property definition
         * @return the current builder
         */
        public DiscriminatorJdbcSubBuilder addMapping(String column, int index, FieldMapperColumnDefinition columnDefinition) {
            initBuilder();
            builder.addMapping(column, index, columnDefinition);
            return this;
        }

        /**
         * @see DiscriminatorJdbcBuilder
         * @return return a DiscriminatorMapper based on the current state of the builder
         */
        public JdbcMapper mapper() {
            return DiscriminatorJdbcBuilder.this.mapper();
        }

        /**
         * Add a discriminator matching predicate with its associated type.
         * @param value the value
         * @param type the type
         * @return the current builder
         */
        public DiscriminatorJdbcSubBuilder when(String value, Type type) {
            return DiscriminatorJdbcBuilder.this.when(value, type);
        }

        /**
         * Add a discriminator value with its associated type.
         * @param value the value
         * @param type the type
         * @return the current builder
         */
        public DiscriminatorJdbcSubBuilder when(String value, Class type) {
            return when(value, (Type)type);
        }

        /**
         * Add a discriminator value with its associated type.
         * @param value the value
         * @param type the type
         * @return the current builder
         */
        public DiscriminatorJdbcSubBuilder when(String value, TypeReference type) {
            return when(value, type.getType());
        }

        /**
         * Add a discriminator matching predicate with its associated type.
         * @param predicate the predicate
         * @param type the type
         * @return the current builder
         */
        public DiscriminatorJdbcSubBuilder when(Predicate predicate, Type type) {
            return DiscriminatorJdbcBuilder.this.when(predicate, type);
        }

        private JdbcSourceFieldMapper createMapper() {
            if (builder != null) {
                return builder.newSourceFieldMapper();
            } else {
                return jdbcMapperFactory.newSourceFieldMapper(type);
            }
        }
    }
 }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy