Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.simpleflatmapper.reflect.meta.ObjectPropertyFinder Maven / Gradle / Ivy
package org.simpleflatmapper.reflect.meta;
import org.simpleflatmapper.reflect.InstantiatorDefinition;
import org.simpleflatmapper.reflect.Parameter;
import org.simpleflatmapper.reflect.property.EligibleAsNonMappedProperty;
import org.simpleflatmapper.reflect.property.OptionalProperty;
import org.simpleflatmapper.util.BooleanProvider;
import java.lang.reflect.Type;
import java.util.*;
final class ObjectPropertyFinder extends PropertyFinder {
enum State {
NONE, SELF, PROPERTIES
}
private final List eligibleInstantiatorDefinitions;
private final ObjectClassMeta classMeta;
private final Map, PropertyFinder> subPropertyFinders = new HashMap, PropertyFinder>();
private State state = State.NONE;
private String selfName;
ObjectPropertyFinder(ObjectClassMeta classMeta, boolean selfScoreFullName) {
super(selfScoreFullName);
this.classMeta = classMeta;
this.eligibleInstantiatorDefinitions = classMeta.getInstantiatorDefinitions() != null ? new ArrayList(classMeta.getInstantiatorDefinitions()) : null;
}
@SuppressWarnings("unchecked")
@Override
public void lookForProperties(final PropertyNameMatcher propertyNameMatcher,
Object[] properties, FoundProperty matchingProperties,
PropertyMatchingScore score,
boolean allowSelfReference,
PropertyFinderTransformer propertyFinderTransform,
TypeAffinityScorer typeAffinityScorer, PropertyFilter propertyFilter) {
lookForConstructor(propertyNameMatcher, properties, matchingProperties, score, propertyFinderTransform, typeAffinityScorer, propertyFilter);
lookForProperty(propertyNameMatcher, properties, matchingProperties, score, propertyFinderTransform, typeAffinityScorer, propertyFilter);
final String propName = propertyNameMatcher.toString();
if (allowSelfReference
&& !disallowSelfReference(properties)
&& (state == State.NONE || (state == State.SELF && propName.equals(selfName)))) {
SelfPropertyMeta propertyMeta = new SelfPropertyMeta(classMeta.getReflectionService(), classMeta.getType(), new BooleanProvider() {
@Override
public boolean getBoolean() {
return state != State.PROPERTIES;
}
}, properties, propertyNameMatcher.toString(), classMeta);
if (propertyFilter.testProperty(propertyMeta)) {
matchingProperties.found(propertyMeta,
selfPropertySelectionCallback(propName),
score.self(classMeta, propName),
typeAffinityScorer);
}
}
if (isOptionalAndEligibleAsNonMappedProperty(properties)) {
NonMappedPropertyMeta meta = new NonMappedPropertyMeta(propertyNameMatcher.toString(), classMeta.getType(), classMeta.getReflectionService(), properties);
matchingProperties.found(
meta,
new Runnable() {
@Override
public void run() {
}
},
score.notMatch(),
typeAffinityScorer);
}
}
public static boolean isOptionalAndEligibleAsNonMappedProperty(Object[] properties) {
return containsProperty(properties, OptionalProperty.class) && containsProperty(properties, EligibleAsNonMappedProperty.class);
}
public static boolean containsProperty(Object[] properties, Class propClass) {
for(Object p : properties) {
if (propClass.isAssignableFrom(p.getClass())) {
return true;
}
}
return false;
}
private boolean disallowSelfReference(Object[] properties) {
if (classMeta.getNumberOfProperties() <= 1) return false;
return containsProperty(properties, DisallowSelfReference.class);
}
private void lookForConstructor(final PropertyNameMatcher propertyNameMatcher, Object[] properties, final FoundProperty matchingProperties, final PropertyMatchingScore score, final PropertyFinderTransformer propertyFinderTransformer, TypeAffinityScorer typeAffinityScorer, PropertyFilter propertyFilter) {
if (classMeta.getConstructorProperties() != null) {
for (final ConstructorPropertyMeta prop : classMeta.getConstructorProperties()) {
final String columnName = getColumnName(prop);
PropertyNameMatch matches = propertyNameMatcher.matches(columnName);
if (matches != null
&& hasConstructorMatching(prop.getParameter())) {
if (propertyFilter.testProperty(prop)) {
matchingProperties.found(prop, propertiesRemoveNonMatchingCallBack(prop), score.matches(matches), typeAffinityScorer);
}
}
if (propertyFilter.testPath(prop)) {
PropertyNameMatch partialMatch = propertyNameMatcher.partialMatch(columnName);
if (partialMatch != null && hasConstructorMatching(prop.getParameter())) {
PropertyNameMatcher subPropMatcher = partialMatch.getLeftOverMatcher();
lookForSubProperty(subPropMatcher, properties, prop, new FoundProperty() {
@Override
public void found(final PropertyMeta propertyMeta, final Runnable selectionCallback, final PropertyMatchingScore score, TypeAffinityScorer typeAffinityScorer) {
matchingProperties.found(
new SubPropertyMeta(classMeta.getReflectionService(), prop, propertyMeta),
propertiesDelegateAndRemoveNonMatchingCallBack(selectionCallback, prop), score, typeAffinityScorer);
}
}, score.matches(partialMatch), propertyFinderTransformer, typeAffinityScorer, propertyFilter);
}
}
}
}
}
private void lookForProperty(final PropertyNameMatcher propertyNameMatcher, Object[] properties, final FoundProperty matchingProperties, final PropertyMatchingScore score, final PropertyFinderTransformer propertyFinderTransformer, TypeAffinityScorer typeAffinityScorer, PropertyFilter propertyFilter) {
for (final PropertyMeta prop : classMeta.getProperties()) {
final String columnName =
hasAlias(properties)
? prop.getName()
: getColumnName(prop);
PropertyNameMatch matches = propertyNameMatcher.matches(columnName);
if (matches != null) {
if (propertyFilter.testProperty(prop)) {
matchingProperties.found(prop, propertiesCallBack(), score.matches(matches), typeAffinityScorer);
}
}
if (propertyFilter.testPath(prop)) {
final PropertyNameMatch subPropMatch = propertyNameMatcher.partialMatch(columnName);
if (subPropMatch != null) {
final PropertyNameMatcher subPropMatcher = subPropMatch.getLeftOverMatcher();
lookForSubProperty(subPropMatcher, properties, prop, new FoundProperty() {
@Override
public void found(final PropertyMeta propertyMeta, final Runnable selectionCallback, final PropertyMatchingScore score, TypeAffinityScorer typeAffinityScorer) {
matchingProperties.found(new SubPropertyMeta(classMeta.getReflectionService(), prop, propertyMeta),
propertiesDelegateCallBack(selectionCallback), score, typeAffinityScorer);
}
}, score.matches(subPropMatch),
propertyFinderTransformer, typeAffinityScorer, propertyFilter);
}
}
}
}
private boolean hasAlias(Object[] properties) {
for(Object o : properties) {
if ("org.simpleflatmapper.map.property.RenameProperty".equals(o.getClass().getName())) // not so great... well
return true;
}
return false;
}
private void lookForSubProperty(
final PropertyNameMatcher propertyNameMatcher,
Object[] properties, final PropertyMeta prop,
final FoundProperty foundProperty,
final PropertyMatchingScore score,
final PropertyFinderTransformer propertyFinderTransformer, TypeAffinityScorer typeAffinityScorer, PropertyFilter propertyFilter) {
PropertyFinder subPropertyFinder = subPropertyFinders.get(prop);
final PropertyFinder newPropertyFinder;
if (subPropertyFinder == null) {
subPropertyFinder = prop.getPropertyClassMeta().newPropertyFinder();
newPropertyFinder = subPropertyFinder;
} else {
newPropertyFinder = null;
}
propertyFinderTransformer
.apply(subPropertyFinder)
.lookForProperties(propertyNameMatcher, properties, new FoundProperty() {
@Override
public void found(final PropertyMeta propertyMeta, final Runnable selectionCallback, final PropertyMatchingScore score, TypeAffinityScorer typeAffinityScorer) {
if (newPropertyFinder != null) {
subPropertyFinders.put(prop, newPropertyFinder);
}
foundProperty.found(propertyMeta, selectionCallback, score, typeAffinityScorer);
}
}, score, false, propertyFinderTransformer, typeAffinityScorer, propertyFilter);
}
private String getColumnName(PropertyMeta prop) {
return this.classMeta.getAlias(prop.getName());
}
private void removeNonMatching(Parameter param) {
ListIterator li = eligibleInstantiatorDefinitions.listIterator();
while(li.hasNext()){
InstantiatorDefinition cd = li.next();
if (!cd.hasParam(param)) {
li.remove();
}
}
}
private boolean hasConstructorMatching(Parameter param) {
for(InstantiatorDefinition cd : eligibleInstantiatorDefinitions) {
if (cd.hasParam(param)) {
return true;
}
}
return false;
}
private Runnable compose(final Runnable r1, final Runnable r2) {
return new Runnable() {
@Override
public void run() {
r1.run();
r2.run();
}
};
}
private Runnable propertiesDelegateAndRemoveNonMatchingCallBack(final Runnable selectionCallback, final ConstructorPropertyMeta prop) {
return compose(selectionCallback, propertiesRemoveNonMatchingCallBack(prop));
}
private Runnable propertiesRemoveNonMatchingCallBack(final ConstructorPropertyMeta prop) {
return compose(removeNonMatchingCallBack(prop), propertiesCallBack());
}
private Runnable removeNonMatchingCallBack(final ConstructorPropertyMeta prop) {
return new Runnable() {
@Override
public void run() {
removeNonMatching(prop.getParameter());
}
};
}
private Runnable propertiesDelegateCallBack(final Runnable selectionCallback) {
return compose(selectionCallback, propertiesCallBack());
}
private Runnable propertiesCallBack() {
return new Runnable() {
@Override
public void run() {
state = State.PROPERTIES;
}
};
}
private Runnable selfPropertySelectionCallback(final String propName) {
return new Runnable() {
@Override
public void run() {
state = State.SELF;
selfName = propName;
}
};
}
@Override
public List getEligibleInstantiatorDefinitions() {
return eligibleInstantiatorDefinitions;
}
@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;
}
@Override
public Type getOwnerType() {
return classMeta.getType();
}
@Override
public void manualMatch(PropertyMeta prop) {
if (prop.isConstructorProperty()) {
removeNonMatching(((ConstructorPropertyMeta) prop).getParameter());
}
super.manualMatch(prop);
}
}