Skip to content

Commit

Permalink
DATACMNS-34 - Improved algorithm to lookup preferred constructor.
Browse files Browse the repository at this point in the history
Algorithm is now was follows:

1. If there's no explicit constructor use the default constructor.
2. If there's a single explicit constructor, use this one.
3. If there's multiple explicit constructors and one has been annotated with @PersistenceConstructor use the annotated one.
4. If there's multiple explicit constructors and none annotated use the no-arg one or throw an exception to resolve the ambiguity.

Test cases for that algorithm are located in PreferredConstructorDiscovererUnitTests. Refactored PreferredConstructor and Parameter classes a little to make them immutable value objects. Introduced ability to lookup parameter TypeInformation for constructors on TypeInformation interface.

Extended generics in mapping subsystem to allow defining a concrete subtype of PersistentProperty as well. Removed some generics related compiler warnings as well.
  • Loading branch information
odrotbohm committed May 10, 2011
1 parent ff51b13 commit 870d156
Show file tree
Hide file tree
Showing 32 changed files with 665 additions and 405 deletions.
Expand Up @@ -35,16 +35,13 @@
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.mapping.event.MappingContextEvent;
import org.springframework.data.mapping.model.MappingContext;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.model.PersistentEntity;
import org.springframework.data.mapping.model.PersistentProperty;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldCallback;
import org.springframework.validation.Validator;
Expand All @@ -58,12 +55,12 @@
* @author Jon Brisbin <jbrisbin@vmware.com>
* @author Oliver Gierke
*/
public abstract class AbstractMappingContext<E extends BasicPersistentEntity<?>, P extends PersistentProperty> implements MappingContext<E>, InitializingBean, ApplicationEventPublisherAware {
public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?, P>, P extends PersistentProperty<P>> implements MappingContext<E, P>, InitializingBean, ApplicationEventPublisherAware {

private static final Set<String> UNMAPPED_FIELDS = new HashSet<String>(Arrays.asList("class", "this$0"));

private ApplicationEventPublisher applicationEventPublisher;
private ConcurrentMap<TypeInformation, E> persistentEntities = new ConcurrentHashMap<TypeInformation, E>();
private ConcurrentMap<TypeInformation<?>, E> persistentEntities = new ConcurrentHashMap<TypeInformation<?>, E>();
private ConcurrentMap<E, List<Validator>> validators = new ConcurrentHashMap<E, List<Validator>>();
private List<Class<?>> customSimpleTypes = new ArrayList<Class<?>>();
private Set<? extends Class<?>> initialEntitySet = new HashSet<Class<?>>();
Expand Down Expand Up @@ -114,14 +111,14 @@ public Collection<E> getPersistentEntities() {
*/
public E getPersistentEntity(Class<?> type) {

return getPersistentEntity(new ClassTypeInformation(type));
return getPersistentEntity(ClassTypeInformation.from(type));
}

/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.MappingContext#getPersistentEntity(org.springframework.data.util.TypeInformation)
*/
public E getPersistentEntity(TypeInformation type) {
public E getPersistentEntity(TypeInformation<?> type) {

E entity = persistentEntities.get(type);

Expand All @@ -144,7 +141,7 @@ public E getPersistentEntity(TypeInformation type) {
*/
protected E addPersistentEntity(Class<?> type) {

return addPersistentEntity(new ClassTypeInformation(type));
return addPersistentEntity(ClassTypeInformation.from(type));
}

/**
Expand All @@ -153,7 +150,7 @@ protected E addPersistentEntity(Class<?> type) {
* @param typeInformation
* @return
*/
protected E addPersistentEntity(TypeInformation typeInformation) {
protected E addPersistentEntity(TypeInformation<?> typeInformation) {

E persistentEntity = persistentEntities.get(typeInformation);

Expand Down Expand Up @@ -195,7 +192,7 @@ public void doWith(Field field) throws IllegalArgumentException, IllegalAccessEx
entity.setIdProperty(property);
}

TypeInformation nestedType = getNestedTypeToAdd(property, entity);
TypeInformation<?> nestedType = getNestedTypeToAdd(property, entity);
if (nestedType != null) {
addPersistentEntity(nestedType);
}
Expand All @@ -212,11 +209,11 @@ public boolean matches(Field field) {

// Inform listeners
if (null != applicationEventPublisher) {
applicationEventPublisher.publishEvent(new MappingContextEvent(entity, typeInformation));
applicationEventPublisher.publishEvent(new MappingContextEvent<E, P>(entity, typeInformation));
}

// Cache
persistentEntities.put(entity.getPropertyInformation(), (E) entity);
persistentEntities.put(entity.getTypeInformation(), (E) entity);

return entity;
} catch (IntrospectionException e) {
Expand All @@ -233,13 +230,13 @@ public boolean matches(Field field) {
* @param property
* @return the TypeInformation to be added as {@link PersistentEntity} or {@literal
*/
private TypeInformation getNestedTypeToAdd(PersistentProperty property, PersistentEntity<?> entity) {
private TypeInformation<?> getNestedTypeToAdd(P property, PersistentEntity<?, P> entity) {

if (entity.getType().equals(property.getRawType())) {
return null;
}

TypeInformation typeInformation = property.getTypeInformation();
TypeInformation<?> typeInformation = property.getTypeInformation();

if (customSimpleTypes.contains(typeInformation.getType())) {
return null;
Expand All @@ -260,15 +257,15 @@ private TypeInformation getNestedTypeToAdd(PersistentProperty property, Persiste
return null;
}

private TypeInformation getTypeInformationIfNotSimpleType(TypeInformation information) {
private TypeInformation<?> getTypeInformationIfNotSimpleType(TypeInformation<?> information) {
return information == null || MappingBeanHelper.isSimpleType(information.getType()) ? null : information;
}

public List<Validator> getEntityValidators(E entity) {
return validators.get(entity);
}

protected abstract E createPersistentEntity(TypeInformation typeInformation);
protected abstract <T> E createPersistentEntity(TypeInformation<T> typeInformation);

protected abstract P createPersistentProperty(Field field, PropertyDescriptor descriptor, E owner);

Expand Down
Expand Up @@ -35,27 +35,29 @@
* @author Jon Brisbin <jbrisbin@vmware.com>
* @author Oliver Gierke
*/
public abstract class AbstractPersistentProperty implements PersistentProperty {
public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>> implements PersistentProperty<P> {

protected final String name;
protected final PropertyDescriptor propertyDescriptor;
protected final TypeInformation information;
protected final TypeInformation<?> information;
protected final Class<?> rawType;
protected final Field field;
protected final Association association;
protected final PersistentEntity<?> owner;
protected final Association<P> association;
protected final PersistentEntity<?, P> owner;

public AbstractPersistentProperty(Field field, PropertyDescriptor propertyDescriptor, PersistentEntity<?> owner) {
public AbstractPersistentProperty(Field field, PropertyDescriptor propertyDescriptor, PersistentEntity<?, P> owner) {
this.name = field.getName();
this.rawType = field.getType();
this.information = owner.getPropertyInformation().getProperty(this.name);
this.information = owner.getTypeInformation().getProperty(this.name);
this.propertyDescriptor = propertyDescriptor;
this.field = field;
this.association = isAssociation() ? new Association(this, null) : null;
this.association = isAssociation() ? createAssociation() : null;
this.owner = owner;
}

protected abstract Association<P> createAssociation();

public PersistentEntity<?> getOwner() {
public PersistentEntity<?, P> getOwner() {
return owner;
}

Expand All @@ -71,7 +73,7 @@ public Class<?> getRawType() {
return this.rawType;
}

public TypeInformation getTypeInformation() {
public TypeInformation<?> getTypeInformation() {
return information;
}

Expand Down Expand Up @@ -104,7 +106,7 @@ public boolean isAssociation() {
return false;
}

public Association getAssociation() {
public Association<P> getAssociation() {
return association;
}

Expand Down
Expand Up @@ -34,7 +34,7 @@
*
* @author Oliver Gierke
*/
public class AnnotationBasedPersistentProperty extends AbstractPersistentProperty {
public abstract class AnnotationBasedPersistentProperty<P extends PersistentProperty<P>> extends AbstractPersistentProperty<P> {

private final Value value;

Expand All @@ -46,7 +46,7 @@ public class AnnotationBasedPersistentProperty extends AbstractPersistentPropert
* @param owner
*/
public AnnotationBasedPersistentProperty(Field field,
PropertyDescriptor propertyDescriptor, PersistentEntity<?> owner) {
PropertyDescriptor propertyDescriptor, PersistentEntity<?, P> owner) {

super(field, propertyDescriptor, owner);
this.value = field.getAnnotation(Value.class);
Expand Down
Expand Up @@ -17,10 +17,11 @@
package org.springframework.data.mapping;

import org.springframework.data.mapping.model.Association;
import org.springframework.data.mapping.model.PersistentProperty;

/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public interface AssociationHandler {
void doWithAssociation(Association association);
public interface AssociationHandler<P extends PersistentProperty<P>> {
void doWithAssociation(Association<P> association);
}

This file was deleted.

0 comments on commit 870d156

Please sign in to comment.