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

org.simpleflatmapper.map.impl.DiscriminatorPropertyFinder 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.map.impl;

import org.simpleflatmapper.reflect.Getter;
import org.simpleflatmapper.reflect.InstantiatorDefinition;
import org.simpleflatmapper.reflect.ReflectionService;
import org.simpleflatmapper.reflect.Setter;
import org.simpleflatmapper.reflect.meta.ClassMeta;
import org.simpleflatmapper.reflect.meta.PropertyFinder;
import org.simpleflatmapper.reflect.meta.PropertyMatchingScore;
import org.simpleflatmapper.reflect.meta.PropertyMeta;
import org.simpleflatmapper.reflect.meta.PropertyNameMatcher;
import org.simpleflatmapper.reflect.meta.SubPropertyMeta;
import org.simpleflatmapper.util.BiConsumer;
import org.simpleflatmapper.util.Predicate;
import org.simpleflatmapper.util.TypeHelper;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DiscriminatorPropertyFinder extends PropertyFinder {
    private final Map, PropertyFinder> subPropertyFinders = new HashMap, PropertyFinder>();
    private final Type ownerType;
    private final List> implementationPropertyFinders;
    private final ReflectionService reflectionService;

    protected DiscriminatorPropertyFinder(boolean selfScoreFullName, Type ownerType, List> implemetations, ReflectionService reflectionService) {
        super( selfScoreFullName);
        this.ownerType = ownerType;
        this.reflectionService = reflectionService;
        implementationPropertyFinders = new ArrayList>();
        for(ClassMeta cm : implemetations) {
            implementationPropertyFinders.add((PropertyFinder) cm.newPropertyFinder());
        }
    }

    @Override
    public void lookForProperties(PropertyNameMatcher propertyNameMatcher, Object[] properties, final FoundProperty matchingProperties, PropertyMatchingScore score, boolean allowSelfReference, PropertyFinderTransformer propertyFinderTransformer, TypeAffinityScorer typeAffinityScorer, PropertyFilter propertyFilter) {
        
        final List matches = new ArrayList();

        PropertyMatchingScore bestScore = null;
        for(PropertyFinder propertyFinder : implementationPropertyFinders) {
            final List matchedProperties = new ArrayList();            
            
            propertyFinder.lookForProperties(propertyNameMatcher, properties,
                    new FoundProperty() {
                        @Override
                        public void found(PropertyMeta propertyMeta, Runnable selectionCallback, PropertyMatchingScore score, TypeAffinityScorer typeAffinityScorer) {
                            matchedProperties.add(new MatchedProperty(propertyMeta, selectionCallback, score, typeAffinityScorer.score(propertyMeta.getPropertyType())));  
                        }
                    }
                    , score, false, propertyFinderTransformer, typeAffinityScorer, propertyFilter);
            
            if (!matchedProperties.isEmpty()) {
                Collections.sort(matchedProperties);
                MatchedProperty selectedMatchedProperty = matchedProperties.get(0);
                matches.add(new DiscriminatorMatch(propertyFinder.getOwnerType(), selectedMatchedProperty));
                
                if (bestScore == null || bestScore.compareTo(selectedMatchedProperty.getScore()) > 0) {
                    bestScore = selectedMatchedProperty.getScore();
                }
            }
        }
        
        if (!matches.isEmpty()) {
            
            DiscriminatorPropertyMeta discriminatorPropertyMeta = new DiscriminatorPropertyMeta("unknown", ownerType,  reflectionService, matches);
            Runnable selectionCallback = new Runnable() {
                @Override
                public void run() {
                    for(DiscriminatorMatch dm : matches) {
                        dm.matchedProperty.select();
                    }
                }
            };
            
            matchingProperties.found(discriminatorPropertyMeta, selectionCallback, bestScore, typeAffinityScorer);
        }
        
    }

    public  PropertyFinder getImplementationPropertyFinder(Type implementationType) {
        for(PropertyFinder pf : implementationPropertyFinders) {
            if(TypeHelper.areEquals(pf.getOwnerType(), implementationType)) {
                return (PropertyFinder) pf;
            }
        }
        throw new IllegalArgumentException("Could not find implementation propertyfinder for " + implementationType);
    }

    private static class DiscriminatorMatch {
        private final Type type;
        private final MatchedProperty matchedProperty;

        private DiscriminatorMatch(Type type, MatchedProperty matchedProperty) {
            this.type = type;
            this.matchedProperty = matchedProperty;
        }
    }

    @Override
    public List getEligibleInstantiatorDefinitions() {
        return null;
    }

    @Override
    public PropertyFinder getSubPropertyFinder(PropertyMeta owner) {
        return subPropertyFinders.get(owner);
    }

    @Override
    public PropertyFinder getOrCreateSubPropertyFinder(SubPropertyMeta subPropertyMeta) {
        PropertyFinder propertyFinder = subPropertyFinders.get(subPropertyMeta.getOwnerProperty());

        if (propertyFinder == null) {
            propertyFinder = subPropertyMeta.getSubProperty().getPropertyClassMeta().newPropertyFinder();
            subPropertyFinders.put(subPropertyMeta.getOwnerProperty(), propertyFinder);
        }

        return propertyFinder;
    }

    public void manualMatch(PropertyMeta prop) {
        if (!(prop instanceof DiscriminatorPropertyMeta)) {
            super.manualMatch(prop);
        }
        DiscriminatorPropertyMeta dpm = (DiscriminatorPropertyMeta) prop;
        
        dpm.forEachProperty(new BiConsumer>() {
            @Override
            public void accept(Type type, PropertyMeta propertyMeta) {
                PropertyFinder pf = getImplementationPropertyFinder(type);
                pf.manualMatch(propertyMeta);
            }
        });
    }


    @Override
    public Type getOwnerType() {
        return ownerType;
    }
    
    
    public static class DiscriminatorPropertyMeta extends PropertyMeta {

        private final List matches;

        public DiscriminatorPropertyMeta(String name, Type ownerType, ReflectionService reflectService, List matches) {
            super(name, ownerType, reflectService);
            this.matches = matches;
        }
        
        public >> C forEachProperty(C consumer) {
            for(DiscriminatorMatch dm : matches) {
                consumer.accept(dm.type, dm.matchedProperty.getPropertyMeta());
            }
            return consumer;
        }

        @Override
        public Setter getSetter() {
            throw new UnsupportedOperationException();
        }

        @Override
        public Getter getGetter() {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean isConstructorProperty() {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean isSubProperty() {
            throw new UnsupportedOperationException();
        }

        @Override
        public Type getPropertyType() {
            Type t = null;

            int i = 0;
            while (i < matches.size()){
                Type te = matches.get(0).matchedProperty.getPropertyMeta().getPropertyType();
                if (t == null) {
                    t = te;
                } else if (!t.equals(te)) {
                    throw new UnsupportedOperationException();
                }
                i++;
            }

            return t;
        }

        @Override
        public String getPath() {
            return matches.get(0).matchedProperty.getPropertyMeta().getPath();
        }

        @Override
        public PropertyMeta withReflectionService(ReflectionService reflectionService) {
            throw new UnsupportedOperationException();
        }

        @Override
        public int typeAffinityScore(TypeAffinityScorer typeAffinityScorer) {
            int bestScore = -1;
            for(DiscriminatorMatch dm : matches) {
                bestScore = Math.max(bestScore,  dm.matchedProperty.getPropertyMeta().typeAffinityScore(typeAffinityScorer));
            }
            return bestScore;
        }

        @Override
        public PropertyMeta toNonMapped() {
            throw new UnsupportedOperationException();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy