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

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

package org.simpleflatmapper.jdbc;


import org.simpleflatmapper.converter.ContextFactoryBuilder;
import org.simpleflatmapper.jdbc.impl.CollectionIndexFieldMapper;
import org.simpleflatmapper.jdbc.impl.MultiIndexQueryPreparer;
import org.simpleflatmapper.jdbc.impl.PreparedStatementIndexedSetterFactory;
import org.simpleflatmapper.jdbc.impl.SingleIndexFieldMapper;
import org.simpleflatmapper.jdbc.impl.MapperQueryPreparer;
import org.simpleflatmapper.jdbc.impl.setter.PreparedStatementIndexSetter;
import org.simpleflatmapper.jdbc.impl.setter.PreparedStatementIndexSetterOnGetter;
import org.simpleflatmapper.jdbc.named.NamedSqlQuery;
import org.simpleflatmapper.map.MappingContext;
import org.simpleflatmapper.map.context.MappingContextFactoryBuilder;
import org.simpleflatmapper.map.mapper.AbstractConstantTargetMapperBuilder;
import org.simpleflatmapper.map.MapperConfig;
import org.simpleflatmapper.map.mapper.ColumnDefinition;
import org.simpleflatmapper.map.property.FieldMapperColumnDefinition;
import org.simpleflatmapper.jdbc.property.IndexedSetterFactoryProperty;
import org.simpleflatmapper.jdbc.property.IndexedSetterProperty;
import org.simpleflatmapper.map.mapper.ConstantTargetFieldMapperFactory;
import org.simpleflatmapper.map.mapper.PropertyMapping;
import org.simpleflatmapper.map.setter.ContextualIndexedSetter;
import org.simpleflatmapper.map.setter.ContextualIndexedSetterAdapter;
import org.simpleflatmapper.map.setter.ContextualIndexedSetterFactory;
import org.simpleflatmapper.reflect.BiInstantiator;
import org.simpleflatmapper.reflect.Getter;
import org.simpleflatmapper.reflect.IndexedGetter;
import org.simpleflatmapper.reflect.IndexedSetter;
import org.simpleflatmapper.reflect.IndexedSetterFactory;
import org.simpleflatmapper.reflect.getter.ArrayIndexedGetter;
import org.simpleflatmapper.reflect.getter.ArraySizeGetter;
import org.simpleflatmapper.reflect.getter.ListIndexedGetter;
import org.simpleflatmapper.reflect.getter.ListSizeGetter;
import org.simpleflatmapper.reflect.meta.*;
import org.simpleflatmapper.reflect.primitive.IntGetter;
import org.simpleflatmapper.util.ConstantPredicate;
import org.simpleflatmapper.util.ErrorDoc;
import org.simpleflatmapper.util.ForEachCallBack;
import org.simpleflatmapper.util.TypeHelper;

import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.List;


public class PreparedStatementMapperBuilder extends AbstractConstantTargetMapperBuilder> {

    private ContextualIndexedSetterFactory> indexedSetterFactory = PreparedStatementIndexedSetterFactory.INSTANCE;

    public PreparedStatementMapperBuilder(
            ClassMeta classMeta,
            MapperConfig mapperConfig,
            ConstantTargetFieldMapperFactory preparedStatementFieldMapperFactory) {
        super(classMeta, PreparedStatement.class, mapperConfig, preparedStatementFieldMapperFactory);
    }

    private PreparedStatementMapperBuilder(PreparedStatementMapperBuilder builder) {
        this(builder.classMeta, builder.mapperConfig, builder.fieldAppenderFactory);
    }

    @Override
    protected BiInstantiator, PreparedStatement> getInstantiator() {
        return new NullInstantiator();
    }

    @Override
    protected JdbcColumnKey newKey(String column, int i, FieldMapperColumnDefinition columnDefinition) {
        JdbcColumnKey key = new JdbcColumnKey(column, i);

        SqlTypeColumnProperty typeColumnProperty = columnDefinition.lookFor(SqlTypeColumnProperty.class);

        if (typeColumnProperty == null) {
            ColumnDefinition globalDef = mapperConfig.columnDefinitions().getColumnDefinition(key);
            typeColumnProperty = globalDef.lookFor(SqlTypeColumnProperty.class);
        }

        if (typeColumnProperty != null) {
            return new JdbcColumnKey(key.getName(), key.getIndex(), typeColumnProperty.getSqlType(), key);
        }

        return key;
    }

    private static class NullInstantiator implements BiInstantiator,  PreparedStatement> {
        @Override
        public PreparedStatement newInstance(T o, MappingContext context) throws Exception {
            throw new UnsupportedOperationException();
        }
    }

    protected int getStartingIndex() {
        return 1;
    }

    public QueryPreparer to(NamedSqlQuery query) {
        return to(query, null);
    }

    public QueryPreparer to(NamedSqlQuery query, String[] generatedKeys) {

        PreparedStatementMapperBuilder builder =
                new PreparedStatementMapperBuilder(this);

        return builder.preparedStatementMapper(query, generatedKeys);
    }

    private QueryPreparer preparedStatementMapper(NamedSqlQuery query, String[] generatedKeys) {

        for(int i = 0; i < query.getParametersSize(); i++) {
            addColumn(query.getParameter(i).getName());
        }

        boolean hasMultiIndex =
                propertyMappingsBuilder.forEachProperties(new ForEachCallBack>() {
                    boolean hasMultiIndex;

                    @Override
                    public void handle(PropertyMapping pm) {
                        hasMultiIndex |= isMultiIndex(pm.getPropertyMeta());
                    }


                }).hasMultiIndex;


        if (hasMultiIndex) {
            MappingContextFactoryBuilder mappingContextFactoryBuilder = new MappingContextFactoryBuilder(keySourceGetter(), !mapperConfig.unorderedJoin());
            return new MultiIndexQueryPreparer(query, buildIndexFieldMappers(mappingContextFactoryBuilder), generatedKeys, mappingContextFactoryBuilder.build());
        } else {
            return new MapperQueryPreparer(query, mapper(), generatedKeys);
        }
    }


    private boolean isMultiIndex(PropertyMeta propertyMeta) {
        return
                TypeHelper.isArray(propertyMeta.getPropertyType())
                || TypeHelper.isAssignable(List.class, propertyMeta.getPropertyType());
    }

    @SuppressWarnings("unchecked")
    public MultiIndexFieldMapper[] buildIndexFieldMappers(final ContextFactoryBuilder contextFactoryBuilder) {
        final List> fields = new ArrayList>();

        propertyMappingsBuilder.forEachProperties(new ForEachCallBack>() {
            @Override
            public void handle(PropertyMapping pm) {

                if (isMultiIndex(pm.getPropertyMeta())) {
                    fields.add(newCollectionFieldMapper(pm));
                } else {
                    fields.add(newFieldMapper(pm));
                }
            }

            private  MultiIndexFieldMapper newCollectionFieldMapper(PropertyMapping pm) {

                PropertyMeta propertyMeta = pm.getPropertyMeta();

                IndexedGetter indexedGetter;
                IntGetter sizeGetter;
                Getter collectionGetter = (Getter) propertyMeta.getGetter();


                if (TypeHelper.isAssignable(List.class, propertyMeta.getPropertyType())) {
                    indexedGetter = (IndexedGetter) new ListIndexedGetter

(); sizeGetter = (IntGetter) new ListSizeGetter(); } else if (TypeHelper.isArray(propertyMeta.getPropertyType())) { indexedGetter = (IndexedGetter) new ArrayIndexedGetter

(); sizeGetter = new ArraySizeGetter(); } else { throw new IllegalArgumentException("Unexpected elementMeta" + propertyMeta); } PropertyMeta childProperty = (PropertyMeta) pm.getPropertyMeta().getPropertyClassMeta().newPropertyFinder().findProperty(DefaultPropertyNameMatcher.of("0"), pm.getColumnDefinition().properties(), pm.getColumnKey(), PropertyFinder.PropertyFilter.trueFilter()); final PropertyMapping pmchildProperttMeta = pm.propertyMeta(childProperty); ContextualIndexedSetter setter = getSetter(pmchildProperttMeta); return new CollectionIndexFieldMapper(setter, collectionGetter, sizeGetter, indexedGetter); } private ContextualIndexedSetter getSetter(PropertyMapping pm) { ContextualIndexedSetter setter = null; IndexedSetterProperty indexedSetterProperty = pm.getColumnDefinition().lookFor(IndexedSetterProperty.class); if (indexedSetterProperty != null) { setter = ContextualIndexedSetterAdapter.of((IndexedSetter) indexedSetterProperty.getIndexedSetter()); } if (setter == null) { setter = indexedSetterFactory(pm); } if (setter == null) { mapperConfig.mapperBuilderErrorHandler().accessorNotFound( "Could not find setter for " + pm.getColumnKey() + " type " + pm.getPropertyMeta().getPropertyType() + " path " + pm.getPropertyMeta().getPath() + " See " + ErrorDoc.CTFM_SETTER_NOT_FOUND.toUrl()); } return setter; } private ContextualIndexedSetter indexedSetterFactory(PropertyMapping pm) { ContextualIndexedSetter setter = null; final IndexedSetterFactoryProperty indexedSetterPropertyFactory = pm.getColumnDefinition().lookFor(IndexedSetterFactoryProperty.class); if (indexedSetterPropertyFactory != null) { IndexedSetterFactory> setterFactory = (IndexedSetterFactory>) indexedSetterPropertyFactory.getIndexedSetterFactory(); setter = ContextualIndexedSetterAdapter.of(setterFactory.

getIndexedSetter(pm)); } if (setter == null) { setter = indexedSetterFactory.getIndexedSetter(pm, contextFactoryBuilder); } if (setter == null) { final ClassMeta

classMeta = pm.getPropertyMeta().getPropertyClassMeta(); if (classMeta instanceof ObjectClassMeta) { ObjectClassMeta

ocm = (ObjectClassMeta

) classMeta; if (ocm.getNumberOfProperties() == 1) { PropertyMeta subProp = ocm.getFirstProperty(); final PropertyMapping subPropertyMapping = pm.propertyMeta(subProp); ContextualIndexedSetter subSetter = indexedSetterFactory(subPropertyMapping); if (subSetter != null) { setter = new PreparedStatementIndexSetterOnGetter((PreparedStatementIndexSetter) subSetter, (Getter) subProp.getGetter()); } } } } return setter; } private

MultiIndexFieldMapper newFieldMapper(PropertyMapping pm) { return new SingleIndexFieldMapper(getSetter(pm), pm.getPropertyMeta().getGetter()); } }); return fields.toArray(new MultiIndexFieldMapper[0]); } }