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

org.simpleflatmapper.converter.ConverterService Maven / Gradle / Ivy

Go to download

Java library to map flat record - ResultSet, csv - to java object with minimum configuration and low footprint.

There is a newer version: 9.0.2
Show newest version
package org.simpleflatmapper.converter;

import org.simpleflatmapper.converter.impl.JavaBaseConverterFactoryProducer;
import org.simpleflatmapper.converter.impl.IdentityConverter;
//IFJAVA8_START
import org.simpleflatmapper.converter.impl.time.JavaTimeConverterFactoryProducer;
//IFJAVA8_END
import org.simpleflatmapper.util.Consumer;
import org.simpleflatmapper.util.ProducerServiceLoader;
import org.simpleflatmapper.util.TypeHelper;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.ServiceLoader;
import java.util.Set;

public class ConverterService {


    private static final ConverterService INSTANCE = new ConverterService(getConverterFactories(ConverterService.class.getClassLoader()));

    private static List getConverterFactories(ClassLoader classLoader) {
        final List converterFactories = new ArrayList();

        final Consumer> factoryConsumer = new Consumer>() {
            @Override
            public void accept(ContextualConverterFactory converterFactory) {
                converterFactories.add(converterFactory);
            }
        };

        new JavaBaseConverterFactoryProducer().produce(factoryConsumer);

        //IFJAVA8_START
        new JavaTimeConverterFactoryProducer().produce(factoryConsumer);
        //IFJAVA8_END

        ProducerServiceLoader.produceFromServiceLoader(ServiceLoader.load(ContextualConverterFactoryProducer.class, classLoader), factoryConsumer);
        ProducerServiceLoader.produceFromServiceLoader(ServiceLoader.load(ConverterFactoryProducer.class, classLoader), new Consumer>() {
            @Override
            public void accept(ConverterFactory converterFactory) {
                factoryConsumer.accept(new ContextualConverterFactoryAdapter(converterFactory));
            }
        });

        return converterFactories;
    }


    public static ConverterService getInstance() {
        return INSTANCE;
    }

    public static ConverterService getInstance(ClassLoader classLoader) {
        return new ConverterService(getConverterFactories(classLoader));
    }

    private ConverterService(List converters) {
        this.converters = converters;
    }

    public  Converter findConverter(Class inType, Class

outType, Object... params) { return findConverter((Type)inType, (Type)outType, params); } public Converter findConverter(Type inType, Type outType, Object... params) { DefaultContextFactoryBuilder builder = new DefaultContextFactoryBuilder(); ContextualConverter converter = findConverter((Type) inType, (Type) outType, builder, params); if (converter == null) return null; return new ConverterToContextualAdapter(converter, builder.build()); } public ContextualConverter findConverter(Class inType, Class

outType, ContextFactoryBuilder contextFactoryBuilder, Object... params) { return findConverter((Type)inType, (Type)outType, contextFactoryBuilder, params); } @SuppressWarnings("unchecked") public ContextualConverter findConverter(Type inType, Type outType, ContextFactoryBuilder contextFactoryBuilder, Object... params) { if (TypeHelper.isAssignable(outType, inType)) { return new IdentityConverter(); } List potentials = findConverterFactories(inType, outType, params); ConvertingTypes targetedTypes = new ConvertingTypes(inType, outType); for(ScoredConverterFactory p : potentials) { ContextualConverter converter = p.converterFactory.newConverter(targetedTypes, contextFactoryBuilder, params); if (converter != null) return converter; } return null; } @SuppressWarnings("unchecked") public List findConverterFactories(Type inType, Type outType, Object... params) { return findConverterFactories(inType, outType, params, new HashSet()); } private List findConverterFactories(Type inType, Type outType, Object[] params, Set loopDetector) { List potentials = new ArrayList(); List tails = new ArrayList(); ConvertingTypes targetedTypes = new ConvertingTypes(inType, outType); for(ContextualConverterFactory converterFactory : converters) { ConvertingScore score = converterFactory.score(targetedTypes); int globalScore = score.getScore(); if (globalScore >= 0) { potentials.add(new ScoredConverterFactory(globalScore, converterFactory)); } else { int tailScore = score.getToScore(); if (tailScore >= 0) { tails.add(new ScoredConverterFactory(tailScore, converterFactory)); } } } if (potentials.isEmpty()) { if (tails.size() > 0) { Collections.sort(tails); int currentScore = Integer.MIN_VALUE; for(ScoredConverterFactory sfactory : tails) { // break when score not to the max and have a converter if (! potentials.isEmpty() && currentScore != Integer.MIN_VALUE) { if (currentScore > sfactory.score) { return potentials; } } else { currentScore = sfactory.score; } Type tailFactoryInType = sfactory.converterFactory.getFromType(); if (outType != tailFactoryInType && ! loopDetector.contains(tailFactoryInType)) { // ignore when no progress Set subLoopDetectors = new HashSet(loopDetector); subLoopDetectors.add(tailFactoryInType); List headConverters = findConverterFactories(inType, tailFactoryInType, params, subLoopDetectors); if (!headConverters.isEmpty()) { List tailConverters = findConverterFactories(tailFactoryInType, outType, params, subLoopDetectors); if (!tailConverters.isEmpty()) { for(ScoredConverterFactory hf : headConverters) { try { if (hf.converterFactory.newConverter(new ConvertingTypes(inType, tailFactoryInType), new DefaultContextFactoryBuilder(), params) != null) { for (ScoredConverterFactory tf : tailConverters) { if (hf.converterFactory.newConverter(new ConvertingTypes(tailFactoryInType, outType), new DefaultContextFactoryBuilder(), params) != null) { ComposedConverterFactory composedConverterFactory = new ComposedConverterFactory(hf.converterFactory, tf.converterFactory, tailFactoryInType); int score = composedConverterFactory.score(new ConvertingTypes(inType, outType)).getScore(); potentials.add(new ScoredConverterFactory(score, composedConverterFactory)); break; } } break; } } catch (IllegalStateException e) { // ignore no format } } } } } } } } Collections.sort(potentials); return potentials; } private final List converters; private static class ScoredConverterFactory implements Comparable{ private final int score; private final ContextualConverterFactory converterFactory; private ScoredConverterFactory(int score, ContextualConverterFactory converterFactory) { this.score = score; this.converterFactory = converterFactory; } @Override public int compareTo(ScoredConverterFactory o) { return o.score - score; } } private static class ComposedConverterFactory implements ContextualConverterFactory { private final ContextualConverterFactory headConverterFactory; private final ContextualConverterFactory tailConverterFactory; private final Type tType; private ComposedConverterFactory(ContextualConverterFactory headConverterFactory, ContextualConverterFactory tailConverterFactory, Type tType) { this.headConverterFactory = headConverterFactory; this.tailConverterFactory = tailConverterFactory; this.tType = tType; } @Override public ContextualConverter newConverter(ConvertingTypes targetedTypes, ContextFactoryBuilder contextFactoryBuilder, Object... params) { ContextualConverter head = headConverterFactory.newConverter(new ConvertingTypes(targetedTypes.getFrom(), tType), contextFactoryBuilder, params); if (head == null) return null; ContextualConverter tail = tailConverterFactory.newConverter(new ConvertingTypes(tType, targetedTypes.getTo()), contextFactoryBuilder); if (tail == null) return null; return new ComposedContextualConverter(head, tail); } @Override public ConvertingScore score(ConvertingTypes targetedTypes) { ConvertingScore headScore = headConverterFactory.score(new ConvertingTypes(targetedTypes.getFrom(), tType)); ConvertingScore tailScore = tailConverterFactory.score(new ConvertingTypes(tType, targetedTypes.getTo())); return new ConvertingScore(Math.min(headScore.getFromScore(), tailScore.getFromScore()), Math.min(headScore.getToScore(), tailScore.getToScore())); } @Override public Type getFromType() { return headConverterFactory.getFromType(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy