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

org.simpleflatmapper.reflect.meta.MapPropertyFinder Maven / Gradle / Ivy

package org.simpleflatmapper.reflect.meta;

import org.simpleflatmapper.converter.ContextFactory;
import org.simpleflatmapper.reflect.InstantiatorDefinition;
import org.simpleflatmapper.converter.ContextualConverter;
import org.simpleflatmapper.reflect.property.MapTypeProperty;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

@SuppressWarnings({ "unchecked", "rawtypes" })
public class MapPropertyFinder, K, V> extends PropertyFinder {
    
    public static int NONE = 0;
    public static int COLUMN_AS_KEY = 1;
    public static int KEY_VALUE = 2;

    private final ClassMeta> keyValueClassMeta;
    private final ClassMeta valueMetaData;
    private final ClassMeta mapMeta;
    private final ContextualConverter keyConverter;
    private final ContextFactory keyContextFactory;
    private final Map> finders = new HashMap>();
    private final Map, PropertyFinder> findersByKey = new HashMap, PropertyFinder>();
    private final Map> keys = new HashMap>();
    private final PropertyFinder> keyValuePropertyFinder;
    private final Type keyValueType;
    private final MapKeyValueElementPropertyMeta elementPropertyMeta;

    private int keyValueMode = NONE;

    public MapPropertyFinder(ClassMeta mapMeta, ClassMeta valueMetaData, ContextualConverter keyConverter, ContextFactory keyContextFactory, boolean selfScoreFullName) {
        super(selfScoreFullName);
        this.mapMeta = mapMeta;
        this.valueMetaData = valueMetaData;
        this.keyConverter = keyConverter;
        this.keyValueType = getKeyValueType(mapMeta);
        this.keyValueClassMeta = mapMeta.getReflectionService().getClassMeta(keyValueType);
        this.keyContextFactory = keyContextFactory;
        this.keyValuePropertyFinder = keyValueClassMeta.newPropertyFinder();
        this.elementPropertyMeta = 
            new MapKeyValueElementPropertyMeta(mapMeta.getType(), valueMetaData.getReflectionService(), keyValueType);
    }

    private Type getKeyValueType(ClassMeta mapMeta) {
        final Type mapType = mapMeta.getType();
        if (mapType instanceof ParameterizedType) {
            return new ParameterizedType() {
                @Override
                public Type[] getActualTypeArguments() {
                    return ((ParameterizedType) mapType).getActualTypeArguments();
                }

                @Override
                public Type getRawType() {
                    return MapKeyValueElementPropertyMeta.KeyValue.class;
                }

                @Override
                public Type getOwnerType() {
                    return null;
                }
            };
        } else {
            return MapKeyValueElementPropertyMeta.KeyValue.class;
        }
    }

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


        if (isKeyValueEnabled(properties)) {
            propertyFinderTransformer.apply(keyValuePropertyFinder).lookForProperties(propertyNameMatcher,
                    properties, new FoundProperty() {
                        @Override
                        public void found(final PropertyMeta propertyMeta, final Runnable selectionCallback, final PropertyMatchingScore score, TypeAffinityScorer typeAffinityScorer) {

                            Runnable sCallback = new Runnable() {
                                @Override
                                public void run() {
                                    selectionCallback.run();
                                    keyValueMode = KEY_VALUE;
                                    findersByKey.put(elementPropertyMeta, keyValuePropertyFinder);
                                }
                            };

                            matchingProperties.found(new SubPropertyMeta(propertyMeta.getReflectService(), elementPropertyMeta, propertyMeta), sCallback, score.matches(propertyNameMatcher), typeAffinityScorer);
                        }
                    },
                    score,
                    false, propertyFinderTransformer, typeAffinityScorer, propertyFilter);
        }
        if (isColunnKeyEnabled(properties)) {
            // classic keys set
            for (final PropertyNameMatcherKeyValuePair keyValue : propertyNameMatcher.keyValuePairs()) {
                final PropertyNameMatcher keyMatcher = keyValue.getKey();
                final PropertyNameMatcher valueMatcher = keyValue.getValue();

                final PropertyFinder propertyFinder = getPropertyFinder(keyMatcher);

                propertyFinderTransformer.apply(propertyFinder).lookForProperties(valueMatcher,
                        properties, new FoundProperty() {
                            @Override
                            public 

> void found(final P propertyMeta, final Runnable selectionCallback, final PropertyMatchingScore score, TypeAffinityScorer typeAffinityScorer) { final PropertyMeta keyProperty = keyProperty(keyMatcher); Runnable sCallback = new Runnable() { @Override public void run() { finders.put(keyMatcher, propertyFinder); findersByKey.put(keyProperty, propertyFinder); selectionCallback.run(); keyValueMode = COLUMN_AS_KEY; } }; if (keyProperty != null) { matchingProperties.found(newSubPropertyMeta(keyProperty, propertyMeta), sCallback, score.matches(keyMatcher), typeAffinityScorer); } } }, score, true, propertyFinderTransformer, typeAffinityScorer, propertyFilter); } } } private boolean isColunnKeyEnabled(Object[] properties) { return keyConverter != null || keyValueMode == COLUMN_AS_KEY || (keyValueMode != KEY_VALUE && MapTypeProperty.isColumnKeyEnabled(properties)); } private boolean isKeyValueEnabled(Object[] properties) { return keyConverter == null || keyValueMode == KEY_VALUE || (keyValueMode != COLUMN_AS_KEY && MapTypeProperty.isKeyValueEnabled(properties)); } private PropertyFinder getPropertyFinder(PropertyNameMatcher keyMatcher) { PropertyFinder propertyFinder = finders.get(keyMatcher); if (propertyFinder == null) { propertyFinder = valueMetaData.newPropertyFinder(); } return propertyFinder; } private PropertyMeta newSubPropertyMeta(PropertyMeta keyProperty, PropertyMeta propertyMeta) { return new SubPropertyMeta( valueMetaData.getReflectionService(), (PropertyMeta) keyProperty, (PropertyMeta) propertyMeta); } private PropertyMeta keyProperty(PropertyNameMatcher propertyNameMatcher) { String keyStringValue = propertyNameMatcher.toString(); PropertyMeta propertyMeta = (PropertyMeta) keys.get(keyStringValue); if (propertyMeta == null) { K key; try { key = keyConverter.convert(keyStringValue, keyContextFactory.newContext()); } catch (Exception e) { // invalid key.. return null; } MapElementPropertyMeta mapElementPropertyMeta = new MapElementPropertyMeta( propertyNameMatcher, mapMeta.getType(), valueMetaData.getReflectionService(), valueMetaData, key); keys.put(keyStringValue, mapElementPropertyMeta); propertyMeta = (PropertyMeta) mapElementPropertyMeta; } return propertyMeta; } @Override public List getEligibleInstantiatorDefinitions() { return mapMeta.getInstantiatorDefinitions(); } @Override public PropertyFinder getSubPropertyFinder(PropertyMeta owner) { return findersByKey.get(owner); } @Override public PropertyFinder getOrCreateSubPropertyFinder(SubPropertyMeta subPropertyMeta) { return getSubPropertyFinder(subPropertyMeta.getOwnerProperty()); } @Override public Type getOwnerType() { return mapMeta.getType(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy