org.simpleflatmapper.map.impl.DiscriminatorPropertyFinder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sfm-map Show documentation
Show all versions of sfm-map Show documentation
Java library to map flat record - ResultSet, csv - to java object with minimum configuration and low footprint.
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 extends T>) 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 super O, ? super P> getSetter() {
throw new UnsupportedOperationException();
}
@Override
public Getter super O, ? extends P> 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();
}
}
}