Browse Source

DATACMNS-867 - Overhaul of PersistentEntity API.

Moved getRequired…(…) methods from implementations into interfaces so that implementations inherit them by default.

Expanded generics declaration in PersistentEntities so that PerisistentProperty instances can be properly access from the PersistentEntity instances returned.
pull/194/head
Oliver Gierke 9 years ago
parent
commit
5f7d1ae2f2
  1. 21
      src/main/java/org/springframework/data/mapping/PersistentEntity.java
  2. 4
      src/main/java/org/springframework/data/mapping/PersistentProperty.java
  3. 12
      src/main/java/org/springframework/data/mapping/context/PersistentEntities.java
  4. 34
      src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java
  5. 36
      src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java
  6. 16
      src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java
  7. 2
      src/main/java/org/springframework/data/repository/core/support/PersistentEntityInformation.java

21
src/main/java/org/springframework/data/mapping/PersistentEntity.java

@ -82,6 +82,12 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> { @@ -82,6 +82,12 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> {
*/
Optional<P> getIdProperty();
default P getRequiredIdProperty() {
return getIdProperty().orElseThrow(
() -> new IllegalStateException(String.format("Required identifier property not found for %s!", getType())));
}
/**
* Returns the version property of the {@link PersistentEntity}. Can be {@literal null} in case no version property is
* available on the entity.
@ -94,11 +100,22 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> { @@ -94,11 +100,22 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> {
* Obtains a {@link PersistentProperty} instance by name.
*
* @param name The name of the property
* @return the {@link PersistentProperty} or {@literal null} if it doesn't exist.
* @return the {@link PersistentProperty} or {@literal Optional#empty()} if it doesn't exist.
*/
Optional<P> getPersistentProperty(String name);
P getRequiredPersistentProperty(String name);
/**
* Returns the {@link PersistentProperty} with the given name.
*
* @param name the name of the property, must not be {@literal null} or empty.
* @return the {@link PersistentProperty} with the given name.
* @throws IllegalArgumentException in case no property with the given name exists.
*/
default P getRequiredPersistentProperty(String name) {
return getPersistentProperty(name).orElseThrow(
() -> new IllegalArgumentException(String.format("No property %s found for type %s!", name, getType())));
}
/**
* Returns the property equipped with an annotation of the given type.

4
src/main/java/org/springframework/data/mapping/PersistentProperty.java

@ -91,6 +91,10 @@ public interface PersistentProperty<P extends PersistentProperty<P>> { @@ -91,6 +91,10 @@ public interface PersistentProperty<P extends PersistentProperty<P>> {
Optional<Association<P>> getAssociation();
default Association<P> getRequiredAssociation() {
return getAssociation().orElseThrow(() -> new IllegalStateException("No association found!"));
}
/**
* Returns whether the type of the {@link PersistentProperty} is actually to be regarded as {@link PersistentEntity}
* in turn.

12
src/main/java/org/springframework/data/mapping/context/PersistentEntities.java

@ -20,6 +20,7 @@ import java.util.Optional; @@ -20,6 +20,7 @@ import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.Streamable;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@ -30,7 +31,7 @@ import org.springframework.util.Assert; @@ -30,7 +31,7 @@ import org.springframework.util.Assert;
* @author Oliver Gierke
* @since 1.8
*/
public class PersistentEntities implements Streamable<PersistentEntity<?, ?>> {
public class PersistentEntities implements Streamable<PersistentEntity<?, ? extends PersistentProperty<?>>> {
private final Streamable<? extends MappingContext<?, ?>> contexts;
@ -53,7 +54,7 @@ public class PersistentEntities implements Streamable<PersistentEntity<?, ?>> { @@ -53,7 +54,7 @@ public class PersistentEntities implements Streamable<PersistentEntity<?, ?>> {
* @param type can be {@literal null}.
* @return
*/
public Optional<PersistentEntity<?, ?>> getPersistentEntity(Class<?> type) {
public Optional<PersistentEntity<?, ? extends PersistentProperty<?>>> getPersistentEntity(Class<?> type) {
return contexts.stream()//
.filter(it -> it.hasPersistentEntityFor(type))//
@ -69,7 +70,7 @@ public class PersistentEntities implements Streamable<PersistentEntity<?, ?>> { @@ -69,7 +70,7 @@ public class PersistentEntities implements Streamable<PersistentEntity<?, ?>> {
* @return the {@link PersistentEntity} for the given domain type.
* @throws IllegalArgumentException in case no {@link PersistentEntity} can be found for the given type.
*/
public PersistentEntity<?, ?> getRequiredPersistentEntity(Class<?> type) {
public PersistentEntity<?, ? extends PersistentProperty<?>> getRequiredPersistentEntity(Class<?> type) {
Assert.notNull(type, "Domain type must not be null!");
@ -94,9 +95,10 @@ public class PersistentEntities implements Streamable<PersistentEntity<?, ?>> { @@ -94,9 +95,10 @@ public class PersistentEntities implements Streamable<PersistentEntity<?, ?>> {
* @see java.lang.Iterable#iterator()
*/
@Override
public Iterator<PersistentEntity<?, ?>> iterator() {
public Iterator<PersistentEntity<?, ? extends PersistentProperty<?>>> iterator() {
return contexts.stream().<PersistentEntity<?, ?>> flatMap(it -> it.getPersistentEntities().stream())
return contexts.stream()
.<PersistentEntity<?, ? extends PersistentProperty<?>>> flatMap(it -> it.getPersistentEntities().stream())
.collect(Collectors.toList()).iterator();
}
}

34
src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java

@ -56,8 +56,9 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -56,8 +56,9 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
protected final Optional<Association<P>> association;
private final @Getter PersistentEntity<?, P> owner;
private final @Getter(AccessLevel.PROTECTED) Property property;
private final SimpleTypeHolder simpleTypeHolder;
private final Lazy<Integer> hashCode;
private final Lazy<Boolean> usePropertyAccess;
private final Lazy<Optional<? extends TypeInformation<?>>> entityTypeInformation;
public AbstractPersistentProperty(Property property, PersistentEntity<?, P> owner,
SimpleTypeHolder simpleTypeHolder) {
@ -67,12 +68,19 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -67,12 +68,19 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
this.name = property.getName();
this.rawType = property.getType();
this.information = PropertyPath.from(Pattern.quote(property.getName()), owner.getTypeInformation()).getTypeInformation();
this.information = PropertyPath.from(Pattern.quote(property.getName()), owner.getTypeInformation())
.getTypeInformation();
this.property = property;
this.association = isAssociation() ? Optional.of(createAssociation()) : Optional.empty();
this.owner = owner;
this.simpleTypeHolder = simpleTypeHolder;
this.hashCode = Lazy.of(property::hashCode);
this.usePropertyAccess = Lazy
.of(() -> owner.getType().isInterface() || getField().map(it -> it.equals(CAUSE_FIELD)).orElse(false));
this.entityTypeInformation = Lazy.of(() -> Optional.ofNullable(information.getActualType())//
.filter(it -> !simpleTypeHolder.isSimpleType(it.getType()))//
.filter(it -> !it.isCollectionLike())//
.filter(it -> !it.isMap()));
}
protected abstract Association<P> createAssociation();
@ -124,19 +132,9 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -124,19 +132,9 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
return Collections.emptySet();
}
TypeInformation<?> candidate = getTypeInformationIfEntityCandidate();
return candidate != null ? Collections.singleton(candidate) : Collections.emptySet();
}
private TypeInformation<?> getTypeInformationIfEntityCandidate() {
TypeInformation<?> candidate = information.getActualType();
if (candidate == null || simpleTypeHolder.isSimpleType(candidate.getType())) {
return null;
}
return candidate.isCollectionLike() || candidate.isMap() ? null : candidate;
return entityTypeInformation.get()//
.map(it -> Collections.singleton(it))//
.orElseGet(() -> Collections.emptySet());
}
/*
@ -244,7 +242,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -244,7 +242,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public boolean isEntity() {
return !isTransient() && getTypeInformationIfEntityCandidate() != null;
return !isTransient() && entityTypeInformation.get().isPresent();
}
/*
@ -284,7 +282,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P> @@ -284,7 +282,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess()
*/
public boolean usePropertyAccess() {
return owner.getType().isInterface() || getField().map(it -> it.equals(CAUSE_FIELD)).orElse(false);
return usePropertyAccess.get();
}
/*

36
src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java

@ -37,6 +37,7 @@ import org.springframework.data.annotation.Version; @@ -37,6 +37,7 @@ import org.springframework.data.annotation.Version;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.Optionals;
import org.springframework.util.Assert;
@ -55,8 +56,8 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -55,8 +56,8 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
private final Optional<Value> value;
private final Map<Class<? extends Annotation>, Optional<? extends Annotation>> annotationCache = new HashMap<>();
private Boolean isTransient;
private boolean usePropertyAccess;
private Lazy<Boolean> isTransient;
private Lazy<Boolean> usePropertyAccess;
/**
* Creates a new {@link AnnotationBasedPersistentProperty}.
@ -71,9 +72,12 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -71,9 +72,12 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
populateAnnotationCache(property);
this.usePropertyAccess = findPropertyOrOwnerAnnotation(AccessType.class).map(it -> Type.PROPERTY.equals(it.value()))
.orElse(false);
this.value = findAnnotation(Value.class);
this.usePropertyAccess = Lazy.of(() -> findPropertyOrOwnerAnnotation(AccessType.class)//
.map(it -> Type.PROPERTY.equals(it.value()))//
.orElse(super.usePropertyAccess()));
this.isTransient = Lazy.of(() -> super.isTransient() || isAnnotationPresent(Transient.class)
|| isAnnotationPresent(Value.class) || isAnnotationPresent(Autowired.class));
}
/**
@ -152,20 +156,13 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -152,20 +156,13 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
/**
* Considers plain transient fields, fields annotated with {@link Transient}, {@link Value} or {@link Autowired} as
* transien.
* transient.
*
* @see org.springframework.data.mapping.BasicPersistentProperty#isTransient()
*/
@Override
public boolean isTransient() {
if (this.isTransient == null) {
boolean potentiallyTransient = super.isTransient() || isAnnotationPresent(Transient.class);
this.isTransient = potentiallyTransient || isAnnotationPresent(Value.class)
|| isAnnotationPresent(Autowired.class);
}
return this.isTransient;
return isTransient.get();
}
/*
@ -267,7 +264,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -267,7 +264,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
*/
@Override
public boolean usePropertyAccess() {
return super.usePropertyAccess() || usePropertyAccess;
return usePropertyAccess.get();
}
/*
@ -281,15 +278,12 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp @@ -281,15 +278,12 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
populateAnnotationCache(getProperty());
}
String builder = annotationCache.values().stream()//
.flatMap(Optionals::toStream)//
.map(Object::toString)//
String builder = annotationCache.values().stream() //
.flatMap(it -> Optionals.toStream(it)) //
.map(Object::toString) //
.collect(Collectors.joining(" "));
return builder//
//
//
+ super.toString();
return builder + super.toString();
}
private Stream<Optional<? extends AnnotatedElement>> getAccessors() {

16
src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java

@ -21,7 +21,6 @@ import lombok.RequiredArgsConstructor; @@ -21,7 +21,6 @@ import lombok.RequiredArgsConstructor;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
@ -274,17 +273,6 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -274,17 +273,6 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
return Optional.ofNullable(propertyCache.get(name));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentEntity#getRequiredPersistentProperty(java.lang.String)
*/
@Override
public P getRequiredPersistentProperty(String name) {
return getPersistentProperty(name).orElseThrow(
() -> new IllegalArgumentException(String.format("No property %s found for type %s!", name, getType())));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentEntity#getPersistentProperty(java.lang.Class)
@ -436,8 +424,8 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement @@ -436,8 +424,8 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
public PersistentPropertyAccessor getPropertyAccessor(Object bean) {
Assert.notNull(bean, "Target bean must not be null!");
Assert.isTrue(getType().isInstance(bean), () ->
String.format(TYPE_MISMATCH, bean.getClass().getName(), getType().getName()));
Assert.isTrue(getType().isInstance(bean),
() -> String.format(TYPE_MISMATCH, bean.getClass().getName(), getType().getName()));
return propertyAccessorFactory.getPropertyAccessor(this, bean);
}

2
src/main/java/org/springframework/data/repository/core/support/PersistentEntityInformation.java

@ -32,7 +32,7 @@ import org.springframework.data.repository.core.EntityInformation; @@ -32,7 +32,7 @@ import org.springframework.data.repository.core.EntityInformation;
@SuppressWarnings("unchecked")
public class PersistentEntityInformation<T, ID extends Serializable> extends AbstractEntityInformation<T, ID> {
private final PersistentEntity<T, ?> persistentEntity;
private final PersistentEntity<T, ? extends PersistentProperty<?>> persistentEntity;
/**
* Creates a new {@link PersistableEntityInformation} for the given {@link PersistentEntity}.

Loading…
Cancel
Save