org.sfm.reflect.meta.ObjectPropertyFinder Maven / Gradle / Ivy
package org.sfm.reflect.meta;
import org.sfm.map.MapperBuildingException;
import org.sfm.reflect.ConstructorDefinition;
import org.sfm.reflect.ConstructorParameter;
import java.util.*;
final class ObjectPropertyFinder implements PropertyFinder {
private final List> eligibleConstructorDefinitions;
private final ObjectClassMeta classMeta;
private final Map> subPropertyFinders = new HashMap>();
ObjectPropertyFinder(ObjectClassMeta classMeta) throws MapperBuildingException {
this.classMeta = classMeta;
this.eligibleConstructorDefinitions = classMeta.getConstructorDefinitions() != null ? new ArrayList>(classMeta.getConstructorDefinitions()) : null;
}
/* (non-Javadoc)
* @see org.sfm.reflect.PropertyFinder#findProperty(org.sfm.utils.PropertyNameMatcher)
*/
@SuppressWarnings("unchecked")
@Override
public PropertyMeta findProperty(final PropertyNameMatcher propertyNameMatcher) {
// check for constructor
PropertyMeta prop = lookForConstructor(propertyNameMatcher);
if (prop == null) {
prop = lookForProperty(propertyNameMatcher);
if (prop == null) {
prop = lookForSubPropertyInConstructors(propertyNameMatcher);
if (prop == null) {
prop = lookForSubProperty(propertyNameMatcher);
} else {
ConstructorPropertyMeta constructorProperty = (ConstructorPropertyMeta) ((SubPropertyMeta)prop).getOwnerProperty();
removeNonMatching(constructorProperty.getConstructorParameter());
}
}
} else {
ConstructorPropertyMeta constructorProperty = (ConstructorPropertyMeta) prop;
removeNonMatching(constructorProperty.getConstructorParameter());
}
return (PropertyMeta) prop;
}
@SuppressWarnings("unchecked")
@Override
public ConstructorPropertyMeta findConstructor(ConstructorDefinition constructorDefinition) {
ConstructorPropertyMeta prop = lookForConstructor(constructorDefinition);
if (prop != null) {
removeNonMatching(prop.getConstructorParameter());
}
return (ConstructorPropertyMeta) prop;
}
private ConstructorPropertyMeta lookForConstructor(final ConstructorDefinition constructorDefinition) {
if (classMeta.getConstructorProperties() != null) {
ConstructorParameter parameter = constructorDefinition.getParameters()[0];
for (ConstructorPropertyMeta prop : classMeta.getConstructorProperties()) {
if (prop.getName().equals(parameter.getName())
&& prop.getConstructorParameter().equals(parameter)) {
return prop;
}
}
}
return null;
}
private ConstructorPropertyMeta lookForConstructor(final PropertyNameMatcher propertyNameMatcher) {
if (classMeta.getConstructorProperties() != null) {
for (ConstructorPropertyMeta prop : classMeta.getConstructorProperties()) {
if (propertyNameMatcher.matches(getColumnName(prop))
&& hasConstructorMatching(prop.getConstructorParameter())) {
return prop;
}
}
}
return null;
}
private PropertyMeta lookForProperty(final PropertyNameMatcher propertyNameMatcher) {
for (PropertyMeta prop : classMeta.getProperties()) {
if (propertyNameMatcher.matches(getColumnName(prop))) {
return prop;
}
}
return null;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private PropertyMeta lookForSubPropertyInConstructors(final PropertyNameMatcher propertyNameMatcher) {
if (classMeta.getConstructorProperties() != null) {
for (ConstructorPropertyMeta prop : classMeta.getConstructorProperties()) {
PropertyNameMatcher subPropMatcher = propertyNameMatcher.partialMatch(getColumnName(prop));
if (subPropMatcher != null && hasConstructorMatching(prop.getConstructorParameter())) {
PropertyMeta subProp = lookForSubProperty(subPropMatcher, prop);
if (subProp != null) {
return new SubPropertyMeta(classMeta.getReflectionService(), prop, subProp);
}
}
}
}
return null;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private PropertyMeta lookForSubProperty(final PropertyNameMatcher propertyNameMatcher) {
for (PropertyMeta prop : classMeta.getProperties()) {
PropertyNameMatcher subPropMatcher = propertyNameMatcher.partialMatch(getColumnName(prop));
if (subPropMatcher != null) {
PropertyMeta subProp = lookForSubProperty(subPropMatcher, prop);
if (subProp != null) {
return new SubPropertyMeta(classMeta.getReflectionService(), prop, subProp);
}
}
}
return null;
}
private PropertyMeta lookForSubProperty(
final PropertyNameMatcher propertyNameMatcher,
final PropertyMeta prop) {
PropertyFinder subPropertyFinder = subPropertyFinders.get(getColumnName(prop));
if (subPropertyFinder == null) {
subPropertyFinder = prop.getClassMeta().newPropertyFinder();
subPropertyFinders.put(prop.getName(), subPropertyFinder);
}
return subPropertyFinder.findProperty(propertyNameMatcher);
}
private String getColumnName(PropertyMeta prop) {
return this.classMeta.getAlias(prop.getName());
}
private void removeNonMatching(ConstructorParameter param) {
ListIterator> li = eligibleConstructorDefinitions.listIterator();
while(li.hasNext()){
ConstructorDefinition cd = li.next();
if (!cd.hasParam(param)) {
li.remove();
}
}
}
private boolean hasConstructorMatching(ConstructorParameter param) {
for(ConstructorDefinition cd : eligibleConstructorDefinitions) {
if (cd.hasParam(param)) {
return true;
}
}
return false;
}
@Override
public List> getEligibleConstructorDefinitions() {
return eligibleConstructorDefinitions;
}
}