org.sfm.reflect.meta.ObjectPropertyFinder Maven / Gradle / Ivy
package org.sfm.reflect.meta;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.sfm.map.MapperBuildingException;
import org.sfm.reflect.asm.ConstructorDefinition;
import org.sfm.reflect.asm.ConstructorParameter;
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)
*/
@Override
public PropertyMeta findProperty(final PropertyNameMatcher propertyNameMatcher) {
PropertyMeta prop = null;
// check for constructor
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).getProperty();
removeNonMatching(constructorProperty.getConstructorParameter());
}
}
} else {
ConstructorPropertyMeta constructorProperty = (ConstructorPropertyMeta) prop;
removeNonMatching(constructorProperty.getConstructorParameter());
}
return prop;
}
private ConstructorPropertyMeta lookForConstructor(final PropertyNameMatcher propertyNameMatcher) {
if (classMeta.getConstructorProperties() != null) {
for (ConstructorPropertyMeta prop : classMeta.getConstructorProperties()) {
if (propertyNameMatcher.matches(prop.getName())
&& hasConstructorMatching(prop.getConstructorParameter())) {
return prop;
}
}
}
return null;
}
private PropertyMeta lookForProperty(final PropertyNameMatcher propertyNameMatcher) {
for (PropertyMeta prop : classMeta.getProperties()) {
if (propertyNameMatcher.matches(prop.getName())) {
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(prop.getName());
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(prop.getName());
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(prop.getName());
if (subPropertyFinder == null) {
subPropertyFinder = prop.getClassMeta().newPropertyFinder();
subPropertyFinders.put(prop.getName(), subPropertyFinder);
}
PropertyMeta, ?> subProp = subPropertyFinder.findProperty(propertyNameMatcher);
return subProp;
}
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) {
ListIterator> li = eligibleConstructorDefinitions.listIterator();
while(li.hasNext()){
ConstructorDefinition cd = li.next();
if (cd.hasParam(param)) {
return true;
}
}
return false;
}
@Override
public PropertyMeta findProperty(String propertyName) {
return findProperty(new PropertyNameMatcher(propertyName));
}
@Override
public List> getEligibleConstructorDefinitions() {
return eligibleConstructorDefinitions;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy