DATACMNS-867 - Second draft.

This commit is contained in:
Oliver Gierke
2016-06-21 16:52:28 +02:00
parent 57ed50a730
commit d4811e29d9
222 changed files with 2297 additions and 2138 deletions

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mapping;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import java.util.Optional;
/**
* @author Oliver Gierke
*/
@Value
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class Alias {
public static Alias NONE = new Alias(Optional.empty());
Optional<? extends Object> value;
public static Alias of(Object alias) {
return ofOptional(Optional.of(alias));
}
public static Alias ofOptional(Optional<? extends Object> optional) {
return optional.isPresent() ? new Alias(optional) : NONE;
}
public boolean isPresentButDifferent(Alias other) {
return isPresent() && !hasValue(other.value);
}
public boolean hasValue(Object that) {
return value.filter(it -> it.equals(that)).isPresent();
}
public boolean hasSamePresentValueAs(Alias other) {
return isPresent() && hasValue(other.value);
}
public boolean isPresent() {
return value.isPresent();
}
public <T> Optional<T> mapTyped(Class<T> type) {
return value.filter(it -> type.isInstance(it)).map(it -> type.cast(it));
}
public String toString() {
return value.map(Object::toString).orElse("NONE");
}
}

View File

@@ -29,5 +29,5 @@ public interface IdentifierAccessor {
*
* @return
*/
Optional<? extends Object> getIdentifier();
Optional<Object> getIdentifier();
}

View File

@@ -135,7 +135,7 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> {
*
* @return
*/
Optional<? extends Object> getTypeAlias();
Alias getTypeAlias();
/**
* Returns the {@link TypeInformation} backing this {@link PersistentEntity}.

View File

@@ -89,7 +89,7 @@ public interface PersistentProperty<P extends PersistentProperty<P>> {
Optional<String> getSpelExpression();
Association<P> getAssociation();
Optional<Association<P>> getAssociation();
/**
* Returns whether the type of the {@link PersistentProperty} is actually to be regarded as {@link PersistentEntity}
@@ -199,7 +199,7 @@ public interface PersistentProperty<P extends PersistentProperty<P>> {
* potentially backing field and traverse accessor methods to potentially available super types.
*
* @param annotationType the annotation to look up, must not be {@literal null}.
* @return the annotation of the given type if present or {@literal null} otherwise.
* @return the annotation of the given type.
* @see AnnotationUtils#findAnnotation(Method, Class)
*/
<A extends Annotation> Optional<A> findAnnotation(Class<A> annotationType);

View File

@@ -49,7 +49,7 @@ public interface PersistentPropertyAccessor {
* @param property must not be {@literal null}.
* @return can be {@literal null}.
*/
Optional<? extends Object> getProperty(PersistentProperty<?> property);
Optional<Object> getProperty(PersistentProperty<?> property);
/**
* Returns the underlying bean.

View File

@@ -226,9 +226,11 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> {
}
private static Optional<String> getValue(Annotation[] annotations) {
return Arrays.stream(annotations).//
filter(it -> it.annotationType() == Value.class).//
findFirst().map(it -> ((Value) it).value());
return Arrays.stream(annotations)//
.filter(it -> it.annotationType() == Value.class)//
.findFirst().map(it -> ((Value) it).value())//
.filter(it -> StringUtils.hasText(it));
}
/**

View File

@@ -16,6 +16,7 @@
package org.springframework.data.mapping;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import java.util.ArrayList;
import java.util.Collections;
@@ -45,7 +46,8 @@ public class PropertyPath implements Streamable<PropertyPath> {
private final TypeInformation<?> owningType;
private final String name;
private final TypeInformation<?> type;
private final @Getter TypeInformation<?> typeInformation;
private final TypeInformation<?> actualTypeInformation;
private final boolean isCollection;
private PropertyPath next;
@@ -57,7 +59,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
* @param owningType must not be {@literal null}.
*/
PropertyPath(String name, Class<?> owningType) {
this(name, ClassTypeInformation.from(owningType), Collections.<PropertyPath> emptyList());
this(name, ClassTypeInformation.from(owningType), Collections.<PropertyPath>emptyList());
}
/**
@@ -74,15 +76,13 @@ public class PropertyPath implements Streamable<PropertyPath> {
Assert.notNull(base, "Perviously found properties must not be null!");
String propertyName = name.matches(ALL_UPPERCASE) ? name : StringUtils.uncapitalize(name);
TypeInformation<?> propertyType = owningType.getProperty(propertyName);
if (propertyType == null) {
throw new PropertyReferenceException(propertyName, owningType, base);
}
TypeInformation<?> propertyType = owningType.getProperty(propertyName)
.orElseThrow(() -> new PropertyReferenceException(propertyName, owningType, base));
this.owningType = owningType;
this.typeInformation = propertyType;
this.isCollection = propertyType.isCollectionLike();
this.type = propertyType.getActualType();
this.actualTypeInformation = propertyType.getActualType();
this.name = propertyName;
}
@@ -127,7 +127,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
* @return
*/
public Class<?> getType() {
return this.type.getType();
return this.actualTypeInformation.getType();
}
/**
@@ -221,7 +221,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
Assert.hasText(source, "Source must not be null or empty!");
Assert.notNull(type, "TypeInformation must not be null or empty!");
List<String> iteratorSource = new ArrayList<String>();
List<String> iteratorSource = new ArrayList<>();
Matcher matcher = SPLITTER.matcher("_" + source);
while (matcher.find()) {
@@ -231,7 +231,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
Iterator<String> parts = iteratorSource.iterator();
PropertyPath result = null;
Stack<PropertyPath> current = new Stack<PropertyPath>();
Stack<PropertyPath> current = new Stack<>();
while (parts.hasNext()) {
if (result == null) {
@@ -256,7 +256,7 @@ public class PropertyPath implements Streamable<PropertyPath> {
PropertyPath previous = base.peek();
PropertyPath propertyPath = create(source, previous.type, base);
PropertyPath propertyPath = create(source, previous.typeInformation.getActualType(), base);
previous.next = propertyPath;
return propertyPath;
}
@@ -298,11 +298,11 @@ public class PropertyPath implements Streamable<PropertyPath> {
base.get(base.size() - 1).next = current;
}
List<PropertyPath> newBase = new ArrayList<PropertyPath>(base);
List<PropertyPath> newBase = new ArrayList<>(base);
newBase.add(current);
if (StringUtils.hasText(addTail)) {
current.next = create(addTail, current.type, newBase);
current.next = create(addTail, current.actualTypeInformation, newBase);
}
return current;

View File

@@ -142,7 +142,7 @@ public class PropertyReferenceException extends RuntimeException {
*/
private static Set<String> detectPotentialMatches(String propertyName, Class<?> type) {
Set<String> result = new HashSet<String>();
Set<String> result = new HashSet<>();
result.addAll(Arrays.asList(PropertyMatches.forField(propertyName, type).getPossibleMatches()));
result.addAll(Arrays.asList(PropertyMatches.forProperty(propertyName, type).getPossibleMatches()));

View File

@@ -29,6 +29,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
@@ -42,8 +43,10 @@ import org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFac
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.model.MutablePersistentEntity;
import org.springframework.data.mapping.model.PersistentPropertyAccessorFactory;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.Pair;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@@ -72,7 +75,8 @@ import org.springframework.util.StringUtils;
public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?, P>, P extends PersistentProperty<P>>
implements MappingContext<E, P>, ApplicationEventPublisherAware, InitializingBean {
private final Map<TypeInformation<?>, E> persistentEntities = new HashMap<TypeInformation<?>, E>();
private final Optional<E> NONE = Optional.empty();
private final Map<TypeInformation<?>, Optional<E>> persistentEntities = new HashMap<>();
private final PersistentPropertyAccessorFactory persistentPropertyAccessorFactory = new ClassGeneratingPropertyAccessorFactory();
private ApplicationEventPublisher applicationEventPublisher;
@@ -132,8 +136,13 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
public Collection<E> getPersistentEntities() {
try {
read.lock();
return Collections.unmodifiableSet(new HashSet<E>(persistentEntities.values()));
return persistentEntities.values().stream()//
.flatMap(it -> Optionals.toStream(it))//
.collect(Collectors.toSet());
} finally {
read.unlock();
}
@@ -143,10 +152,21 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* (non-Javadoc)
* @see org.springframework.data.mapping.model.MappingContext#getPersistentEntity(java.lang.Class)
*/
public E getPersistentEntity(Class<?> type) {
public Optional<E> getPersistentEntity(Class<?> type) {
return getPersistentEntity(ClassTypeInformation.from(type));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.MappingContext#getRequiredPersistentEntity(java.lang.Class)
*/
@Override
public E getRequiredPersistentEntity(Class<?> type) {
return getPersistentEntity(type).orElseThrow(
() -> new IllegalArgumentException(String.format("Couldn't find PersistentEntity for type %s!", type)));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.MappingContext#hasPersistentEntityFor(java.lang.Class)
@@ -160,13 +180,15 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* (non-Javadoc)
* @see org.springframework.data.mapping.model.MappingContext#getPersistentEntity(org.springframework.data.util.TypeInformation)
*/
public E getPersistentEntity(TypeInformation<?> type) {
public Optional<E> getPersistentEntity(TypeInformation<?> type) {
Assert.notNull(type, "Type must not be null!");
try {
read.lock();
E entity = persistentEntities.get(type);
Optional<E> entity = persistentEntities.get(type);
if (entity != null) {
return entity;
@@ -177,7 +199,15 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
}
if (!shouldCreatePersistentEntityFor(type)) {
return null;
try {
write.lock();
persistentEntities.put(type, NONE);
} finally {
write.unlock();
}
return NONE;
}
if (strict) {
@@ -187,20 +217,40 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
return addPersistentEntity(type);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.MappingContext#getRequiredPersistentEntity(org.springframework.data.util.TypeInformation)
*/
@Override
public E getRequiredPersistentEntity(TypeInformation<?> type) {
return getPersistentEntity(type)
.orElseThrow(() -> new MappingException(String.format("Couldn't find PersistentEntity for type %s!", type)));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.MappingContext#getPersistentEntity(org.springframework.data.mapping.PersistentProperty)
*/
public E getPersistentEntity(P persistentProperty) {
public Optional<E> getPersistentEntity(P persistentProperty) {
if (persistentProperty == null) {
return null;
}
Assert.notNull(persistentProperty, "PersistentProperty must not be null!");
TypeInformation<?> typeInfo = persistentProperty.getTypeInformation();
return getPersistentEntity(typeInfo.getActualType());
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.MappingContext#getRequiredPersistentEntity(org.springframework.data.mapping.PersistentProperty)
*/
@Override
public E getRequiredPersistentEntity(P persistentProperty) {
return getPersistentEntity(persistentProperty).orElseThrow(() -> new IllegalArgumentException(
String.format("Couldn't find PersistentEntity for type %s!", persistentProperty)));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.MappingContext#getPersistentPropertyPath(java.lang.Class, java.lang.String)
@@ -248,7 +298,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
DefaultPersistentPropertyPath<P> path = DefaultPersistentPropertyPath.empty();
Iterator<String> iterator = parts.iterator();
E current = getPersistentEntity(type);
E current = getRequiredPersistentEntity(type);
while (iterator.hasNext()) {
@@ -277,8 +327,11 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
Optional<P> persistentProperty = entity.getPersistentProperty(segment);
return persistentProperty.map(it -> Pair.of(path.append(it),
iterator.hasNext() ? getPersistentEntity(it.getTypeInformation().getActualType()) : entity));
return persistentProperty.map(it -> {
TypeInformation<?> type = it.getTypeInformation().getActualType();
return Pair.of(path.append(it), iterator.hasNext() ? getRequiredPersistentEntity(type) : entity);
});
}
/**
@@ -287,7 +340,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* @param type must not be {@literal null}.
* @return
*/
protected E addPersistentEntity(Class<?> type) {
protected Optional<E> addPersistentEntity(Class<?> type) {
return addPersistentEntity(ClassTypeInformation.from(type));
}
@@ -297,7 +350,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* @param typeInformation must not be {@literal null}.
* @return
*/
protected E addPersistentEntity(TypeInformation<?> typeInformation) {
protected Optional<E> addPersistentEntity(TypeInformation<?> typeInformation) {
Assert.notNull(typeInformation, "TypeInformation must not be null!");
@@ -305,11 +358,12 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
read.lock();
E persistentEntity = persistentEntities.get(typeInformation);
Optional<E> persistentEntity = persistentEntities.get(typeInformation);
if (persistentEntity != null) {
return persistentEntity;
}
} finally {
read.unlock();
}
@@ -323,7 +377,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
final E entity = createPersistentEntity(typeInformation);
// Eagerly cache the entity as we might have to find it during recursive lookups.
persistentEntities.put(typeInformation, entity);
persistentEntities.put(typeInformation, Optional.of(entity));
PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(type);
@@ -354,7 +408,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
applicationEventPublisher.publishEvent(new MappingContextEvent<E, P>(this, entity));
}
return entity;
return Optional.of(entity);
} catch (BeansException e) {
throw new MappingException(e.getMessage(), e);
@@ -398,8 +452,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
* @param simpleTypeHolder
* @return
*/
protected abstract P createPersistentProperty(Optional<Field> field, PropertyDescriptor descriptor, E owner,
SimpleTypeHolder simpleTypeHolder);
protected abstract P createPersistentProperty(Property property, E owner, SimpleTypeHolder simpleTypeHolder);
/*
* (non-Javadoc)
@@ -471,7 +524,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
String fieldName = field.getName();
ReflectionUtils.makeAccessible(field);
createAndRegisterProperty(Optional.of(field), descriptors.get(fieldName));
createAndRegisterProperty(Property.of(field, Optional.ofNullable(descriptors.get(fieldName))));
this.remainingDescriptors.remove(fieldName);
}
@@ -486,28 +539,25 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
for (PropertyDescriptor descriptor : remainingDescriptors.values()) {
if (PersistentPropertyFilter.INSTANCE.matches(descriptor)) {
createAndRegisterProperty(Optional.empty(), descriptor);
createAndRegisterProperty(Property.of(descriptor));
}
}
}
private void createAndRegisterProperty(Optional<Field> field, PropertyDescriptor descriptor) {
private void createAndRegisterProperty(Property input) {
P property = createPersistentProperty(field, descriptor, entity, simpleTypeHolder);
P property = createPersistentProperty(input, entity, simpleTypeHolder);
if (property.isTransient()) {
return;
}
if (field == null && !property.usePropertyAccess()) {
if (!input.isFieldBacked() && !property.usePropertyAccess()) {
return;
}
entity.addPersistentProperty(property);
if (property.isAssociation()) {
entity.addAssociation(property.getAssociation());
}
property.getAssociation().ifPresent(it -> entity.addAssociation(it));
if (entity.getType().equals(property.getRawType())) {
return;
@@ -533,7 +583,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
static {
Set<PropertyMatch> matches = new HashSet<PropertyMatch>();
Set<PropertyMatch> matches = new HashSet<>();
matches.add(new PropertyMatch("class", null));
matches.add(new PropertyMatch("this\\$.*", null));
matches.add(new PropertyMatch("metaClass", "groovy.lang.MetaClass"));

View File

@@ -62,7 +62,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
* @return
*/
public static <T extends PersistentProperty<T>> DefaultPersistentPropertyPath<T> empty() {
return new DefaultPersistentPropertyPath<T>(Collections.<T> emptyList());
return new DefaultPersistentPropertyPath<>(Collections.<T> emptyList());
}
/**
@@ -77,17 +77,17 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
Assert.notNull(property, "Property must not be null!");
if (isEmpty()) {
return new DefaultPersistentPropertyPath<T>(Arrays.asList(property));
return new DefaultPersistentPropertyPath<>(Arrays.asList(property));
}
Class<?> leafPropertyType = getLeafProperty().getActualType();
Assert.isTrue(property.getOwner().getType().equals(leafPropertyType),
String.format("Cannot append property %s to type %s!", property.getName(), leafPropertyType.getName()));
List<T> properties = new ArrayList<T>(this.properties);
List<T> properties = new ArrayList<>(this.properties);
properties.add(property);
return new DefaultPersistentPropertyPath<T>(properties);
return new DefaultPersistentPropertyPath<>(properties);
}
/*
@@ -125,7 +125,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
? PropertyNameConverter.INSTANCE : converter);
String delimiterToUse = delimiter == null ? "." : delimiter;
List<String> result = new ArrayList<String>();
List<String> result = new ArrayList<>();
for (T property : properties) {
@@ -193,7 +193,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
return this;
}
List<T> result = new ArrayList<T>();
List<T> result = new ArrayList<>();
Iterator<T> iterator = iterator();
for (int i = 0; i < base.getLength(); i++) {
@@ -204,7 +204,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
result.add(iterator.next());
}
return new DefaultPersistentPropertyPath<T>(result);
return new DefaultPersistentPropertyPath<>(result);
}
/*
@@ -216,7 +216,7 @@ class DefaultPersistentPropertyPath<T extends PersistentProperty<T>> implements
if (size <= 1) {
return this;
}
return new DefaultPersistentPropertyPath<T>(properties.subList(0, size - 1));
return new DefaultPersistentPropertyPath<>(properties.subList(0, size - 1));
}
/*

View File

@@ -16,6 +16,7 @@
package org.springframework.data.mapping.context;
import java.util.Collection;
import java.util.Optional;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
@@ -48,7 +49,9 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
* @param type must not be {@literal null}.
* @return
*/
E getPersistentEntity(Class<?> type);
Optional<E> getPersistentEntity(Class<?> type);
E getRequiredPersistentEntity(Class<?> type);
/**
* Returns whether the {@link MappingContext} currently contains a {@link PersistentEntity} for the type.
@@ -67,25 +70,30 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
* @param type must not be {@literal null}.
* @return
*/
E getPersistentEntity(TypeInformation<?> type);
Optional<E> getPersistentEntity(TypeInformation<?> type);
E getRequiredPersistentEntity(TypeInformation<?> type);
/**
* Returns the {@link PersistentEntity} mapped by the given {@link PersistentProperty}.
*
* @param persistentProperty
* @param persistentProperty must not be {@literal null}.
* @return the {@link PersistentEntity} mapped by the given {@link PersistentProperty} or null if no
* {@link PersistentEntity} exists for it or the {@link PersistentProperty} does not refer to an entity (the
* type of the property is considered simple see
* {@link org.springframework.data.mapping.model.SimpleTypeHolder#isSimpleType(Class)}).
*/
E getPersistentEntity(P persistentProperty);
Optional<E> getPersistentEntity(P persistentProperty);
E getRequiredPersistentEntity(P persistentProperty);
/**
* Returns all {@link PersistentProperty}s for the given path expression based on the given {@link PropertyPath}.
*
* @param propertyPath must not be {@literal null}.
* @return the {@link PersistentPropertyPath} representing the given {@link PropertyPath}.
* @throws InvalidPersistentPropertyPath in case not all of the segments of the given {@link PropertyPath} can be resolved.
* @throws InvalidPersistentPropertyPath in case not all of the segments of the given {@link PropertyPath} can be
* resolved.
*/
PersistentPropertyPath<P> getPersistentPropertyPath(PropertyPath propertyPath);
@@ -100,10 +108,12 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
PersistentPropertyPath<P> getPersistentPropertyPath(String propertyPath, Class<?> type);
/**
* Returns the {@link PersistentPropertyPath} for the resolvable part of the given {@link InvalidPersistentPropertyPath}.
* Returns the {@link PersistentPropertyPath} for the resolvable part of the given
* {@link InvalidPersistentPropertyPath}.
*
* @param invalidPath must not be {@literal null}.
* @return the {@link PersistentPropertyPath} for the resolvable part of the given {@link InvalidPersistentPropertyPath}.
* @return the {@link PersistentPropertyPath} for the resolvable part of the given
* {@link InvalidPersistentPropertyPath}.
* @since 1.11
*/
PersistentPropertyPath<P> getPersistentPropertyPath(InvalidPersistentPropertyPath invalidPath);

View File

@@ -15,12 +15,15 @@
*/
package org.springframework.data.mapping.context;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.Optional;
import java.util.function.Function;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.support.IsNewStrategy;
import org.springframework.data.support.IsNewStrategyFactory;
@@ -69,19 +72,25 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp
@Override
protected IsNewStrategy doGetIsNewStrategy(Class<?> type) {
PersistentEntity<?, ?> entity = context.getPersistentEntity(type);
return context.getPersistentEntity(type)//
.flatMap(it -> foo(it))//
.orElseThrow(() -> new MappingException(String.format("Cannot determine IsNewStrategy for type %s!", type)));
}
if (entity == null) {
return null;
}
private static Optional<IsNewStrategy> foo(PersistentEntity<?, ?> entity) {
if (entity.hasVersionProperty()) {
return new PropertyIsNullOrZeroNumberIsNewStrategy(entity.getVersionProperty().get());
return entity.getVersionProperty().map(it -> PersistentPropertyInspectingIsNewStrategy.of(it,
MappingContextIsNewStrategyFactory::propertyIsNullOrZeroNumber));
} else if (entity.hasIdProperty()) {
return new PropertyIsNullIsNewStrategy(entity.getIdProperty().get());
} else {
throw new MappingException(String.format("Cannot determine IsNewStrategy for type %s!", type));
return entity.getIdProperty().map(
it -> PersistentPropertyInspectingIsNewStrategy.of(it, MappingContextIsNewStrategyFactory::propertyIsNull));
}
return Optional.empty();
}
/**
@@ -90,19 +99,11 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp
*
* @author Oliver Gierke
*/
static abstract class PersistentPropertyInspectingIsNewStrategy implements IsNewStrategy {
@RequiredArgsConstructor(staticName = "of")
static class PersistentPropertyInspectingIsNewStrategy implements IsNewStrategy {
private final PersistentProperty<?> property;
/**
* Creates a new {@link PersistentPropertyInspectingIsNewStrategy} using the given {@link PersistentProperty}.
*
* @param property must not be {@literal null}.
*/
public PersistentPropertyInspectingIsNewStrategy(PersistentProperty<?> property) {
Assert.notNull(property, "PersistentProperty must not be null!");
this.property = property;
}
private final @NonNull PersistentProperty<?> property;
private final @NonNull Function<Optional<Object>, Boolean> isNew;
/*
* (non-Javadoc)
@@ -111,80 +112,26 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp
@Override
public boolean isNew(Optional<? extends Object> entity) {
return entity.map(it -> {
PersistentPropertyAccessor accessor = property.getOwner().getPropertyAccessor(it);
Object propertyValue = accessor.getProperty(property);
return decideIsNew(propertyValue);
}).orElse(false);
}
protected abstract boolean decideIsNew(Object property);
}
/**
* {@link IsNewStrategy} that does a check against {@literal null} for the given value and considers the object new if
* the value given is {@literal null}.
*
* @author Oliver Gierke
*/
static class PropertyIsNullIsNewStrategy extends PersistentPropertyInspectingIsNewStrategy {
/**
* Creates a new {@link PropertyIsNullIsNewStrategy} using the given {@link PersistentProperty}.
*
* @param property must not be {@literal null}.
*/
public PropertyIsNullIsNewStrategy(PersistentProperty<?> property) {
super(property);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.MappingContextIsNewStrategyFactory.PersistentPropertyInspectingIsNewStrategy#decideIsNew(java.lang.Object)
*/
@Override
protected boolean decideIsNew(Object property) {
return property == null;
return entity//
.map(it -> isNew.apply(property.getOwner().getPropertyAccessor(it).getProperty(property)))//
.orElse(false);
}
}
/**
* {@link IsNewStrategy} that considers property values of {@literal null} or 0 (in case of a {@link Number})
* implementation as indicators for the new state.
*
* @author Oliver Gierke
*/
static class PropertyIsNullOrZeroNumberIsNewStrategy extends PersistentPropertyInspectingIsNewStrategy {
private static boolean propertyIsNull(Optional<Object> it) {
return !it.isPresent();
}
/**
* Creates a new {@link PropertyIsNullOrZeroNumberIsNewStrategy} instance using the given {@link PersistentProperty}
* .
*
* @param property must not be {@literal null}.
*/
public PropertyIsNullOrZeroNumberIsNewStrategy(PersistentProperty<?> property) {
super(property);
}
private static boolean propertyIsNullOrZeroNumber(Optional<Object> it) {
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.MappingContextIsNewStrategyFactory.PersistentPropertyInspectingIsNewStrategy#decideIsNew(java.lang.Object)
*/
@Override
protected boolean decideIsNew(Object property) {
return it.map(value -> {
if (property == null) {
return true;
}
if (!(property instanceof Number)) {
if (!(value instanceof Number)) {
return false;
}
return ((Number) property).longValue() == 0;
}
return ((Number) value).longValue() == 0;
}).orElse(true);
}
}

View File

@@ -15,14 +15,12 @@
*/
package org.springframework.data.mapping.context;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.util.Streamable;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@@ -32,9 +30,9 @@ import org.springframework.util.Assert;
* @author Oliver Gierke
* @since 1.8
*/
public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> {
public class PersistentEntities implements Streamable<PersistentEntity<?, ?>> {
private final Iterable<? extends MappingContext<?, ?>> contexts;
private final Streamable<? extends MappingContext<?, ?>> contexts;
/**
* Creates a new {@link PersistentEntities} for the given {@link MappingContext}s.
@@ -44,7 +42,7 @@ public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> {
public PersistentEntities(Iterable<? extends MappingContext<?, ?>> contexts) {
Assert.notNull(contexts, "MappingContexts must not be null!");
this.contexts = contexts;
this.contexts = Streamable.of(contexts);
}
/**
@@ -55,16 +53,11 @@ public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> {
* @param type can be {@literal null}.
* @return
*/
public PersistentEntity<?, ?> getPersistentEntity(Class<?> type) {
public Optional<PersistentEntity<?, ?>> getPersistentEntity(Class<?> type) {
for (MappingContext<?, ?> context : contexts) {
if (context.hasPersistentEntityFor(type)) {
return context.getPersistentEntity(type);
}
}
return null;
return contexts.stream()//
.filter(it -> it.hasPersistentEntityFor(type))//
.findFirst().map(it -> it.getRequiredPersistentEntity(type));
}
/**
@@ -72,15 +65,11 @@ public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> {
*
* @return
*/
public Iterable<TypeInformation<?>> getManagedTypes() {
public Streamable<TypeInformation<?>> getManagedTypes() {
Set<TypeInformation<?>> informations = new HashSet<TypeInformation<?>>();
for (MappingContext<?, ?> context : contexts) {
informations.addAll(context.getManagedTypes());
}
return Collections.unmodifiableSet(informations);
return Streamable.of(contexts.stream()//
.flatMap(it -> it.getManagedTypes().stream())//
.collect(Collectors.toSet()));
}
/*
@@ -90,12 +79,7 @@ public class PersistentEntities implements Iterable<PersistentEntity<?, ?>> {
@Override
public Iterator<PersistentEntity<?, ?>> iterator() {
List<PersistentEntity<?, ?>> entities = new ArrayList<PersistentEntity<?, ?>>();
for (MappingContext<?, ?> context : contexts) {
entities.addAll(context.getPersistentEntities());
}
return entities.iterator();
return contexts.stream().<PersistentEntity<?, ?>>flatMap(it -> it.getPersistentEntities().stream())
.collect(Collectors.toList()).iterator();
}
}

View File

@@ -15,7 +15,9 @@
*/
package org.springframework.data.mapping.model;
import java.beans.PropertyDescriptor;
import lombok.AccessLevel;
import lombok.Getter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collections;
@@ -26,6 +28,8 @@ import org.springframework.data.annotation.Reference;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
@@ -46,43 +50,33 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
}
protected final String name;
protected final Optional<PropertyDescriptor> propertyDescriptor;
protected final TypeInformation<?> information;
protected final Class<?> rawType;
protected final Optional<Field> field;
protected final Association<P> association;
protected final PersistentEntity<?, P> owner;
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 int hashCode;
private final Lazy<Integer> hashCode;
public AbstractPersistentProperty(Optional<Field> field, PropertyDescriptor propertyDescriptor,
PersistentEntity<?, P> owner, SimpleTypeHolder simpleTypeHolder) {
public AbstractPersistentProperty(Property property, PersistentEntity<?, P> owner,
SimpleTypeHolder simpleTypeHolder) {
Assert.notNull(simpleTypeHolder, "SimpleTypeHolder must not be null!");
Assert.notNull(owner, "Owner entity must not be null!");
this.name = field.map(Field::getName).orElseGet(() -> propertyDescriptor.getName());
this.rawType = field.<Class<?>> map(Field::getType).orElseGet(() -> propertyDescriptor.getPropertyType());
this.information = owner.getTypeInformation().getProperty(this.name);
this.propertyDescriptor = Optional.ofNullable(propertyDescriptor);
this.field = field;
this.association = isAssociation() ? createAssociation() : null;
this.name = property.getName();
this.rawType = property.getRawType();
this.information = PropertyPath.from(property.getName(), owner.getTypeInformation()).getTypeInformation();
this.property = property;
this.association = isAssociation() ? Optional.of(createAssociation()) : Optional.empty();
this.owner = owner;
this.simpleTypeHolder = simpleTypeHolder;
this.hashCode = this.field == null ? this.propertyDescriptor.hashCode() : this.field.hashCode();
this.hashCode = Lazy.of(() -> property.hashCode());
}
protected abstract Association<P> createAssociation();
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#getOwner()
*/
@Override
public PersistentEntity<?, P> getOwner() {
return owner;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#getName()
@@ -131,7 +125,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
}
TypeInformation<?> candidate = getTypeInformationIfEntityCandidate();
return candidate != null ? Collections.singleton(candidate) : Collections.<TypeInformation<?>> emptySet();
return candidate != null ? Collections.singleton(candidate) : Collections.<TypeInformation<?>>emptySet();
}
private TypeInformation<?> getTypeInformationIfEntityCandidate() {
@@ -151,8 +145,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public Optional<Method> getGetter() {
return propertyDescriptor.map(it -> it.getReadMethod())//
.filter(it -> rawType.isAssignableFrom(it.getReturnType()));
return property.getGetter();
}
/*
@@ -161,8 +154,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public Optional<Method> getSetter() {
return propertyDescriptor.map(it -> it.getWriteMethod())//
.filter(it -> it.getParameterTypes()[0].isAssignableFrom(rawType));
return property.getSetter();
}
/*
@@ -171,7 +163,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public Optional<Field> getField() {
return field;
return property.getField();
}
/*
@@ -215,7 +207,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
* @see org.springframework.data.mapping.PersistentProperty#getAssociation()
*/
@Override
public Association<P> getAssociation() {
public Optional<Association<P>> getAssociation() {
return association;
}
@@ -266,8 +258,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
return null;
}
TypeInformation<?> componentType = information.getComponentType();
return componentType == null ? null : componentType.getType();
return information.getRequiredComponentType().getType();
}
/*
@@ -276,7 +267,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public Class<?> getMapValueType() {
return isMap() ? information.getMapValueType().getType() : null;
return isMap() ? information.getMapValueType().map(it -> it.getType()).orElse(null) : null;
}
/*
@@ -293,7 +284,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() || CAUSE_FIELD.equals(getField());
return owner.getType().isInterface() || getField().map(it -> it.equals(CAUSE_FIELD)).orElse(false);
}
/*
@@ -313,7 +304,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
AbstractPersistentProperty<?> that = (AbstractPersistentProperty<?>) obj;
return this.field == null ? this.propertyDescriptor.equals(that.propertyDescriptor) : this.field.equals(that.field);
return this.property.equals(that.property);
}
/*
@@ -322,7 +313,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public int hashCode() {
return this.hashCode;
return this.hashCode.get();
}
/*
@@ -331,8 +322,6 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
*/
@Override
public String toString() {
return field.map(Object::toString)//
.orElseGet(() -> propertyDescriptor.map(Object::toString)//
.orElseThrow(() -> new IllegalStateException("Either Field or PropertyDescriptor has to be present!")));
return property.toString();
}
}

View File

@@ -15,10 +15,8 @@
*/
package org.springframework.data.mapping.model;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -63,15 +61,15 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
* Creates a new {@link AnnotationBasedPersistentProperty}.
*
* @param field must not be {@literal null}.
* @param propertyDescriptor can be {@literal null}.
* @param propertyDescriptor must not be {@literal null}.
* @param owner must not be {@literal null}.
*/
public AnnotationBasedPersistentProperty(Optional<Field> field, PropertyDescriptor propertyDescriptor,
PersistentEntity<?, P> owner, SimpleTypeHolder simpleTypeHolder) {
public AnnotationBasedPersistentProperty(Property property, PersistentEntity<?, P> owner,
SimpleTypeHolder simpleTypeHolder) {
super(field, propertyDescriptor, owner, simpleTypeHolder);
super(property, owner, simpleTypeHolder);
populateAnnotationCache(field);
populateAnnotationCache(property);
this.usePropertyAccess = findPropertyOrOwnerAnnotation(AccessType.class).map(it -> Type.PROPERTY.equals(it.value()))
.orElse(false);
@@ -85,9 +83,9 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
* @param field
* @throws MappingException in case we find an ambiguous mapping on the accessor methods
*/
private final void populateAnnotationCache(Optional<Field> field) {
private final void populateAnnotationCache(Property property) {
Optionals.toStream(getGetter(), getSetter()).forEach(it -> {
Optionals.toStream(property.getGetter(), property.getSetter()).forEach(it -> {
for (Annotation annotation : it.getAnnotations()) {
@@ -102,7 +100,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
}
});
field.ifPresent(it -> {
property.getField().ifPresent(it -> {
for (Annotation annotation : it.getAnnotations()) {
@@ -218,10 +216,11 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
return (Optional<A>) annotationCache.get(annotationType);
}
return cacheAndReturn(annotationType, getAccessors()//
.map(it -> it.map(inner -> AnnotatedElementUtils.findMergedAnnotation(inner, annotationType)))//
.flatMap(it -> Optionals.toStream(it))//
.findFirst());
return cacheAndReturn(annotationType,
getAccessors()//
.map(it -> it.map(inner -> AnnotatedElementUtils.findMergedAnnotation(inner, annotationType)))//
.flatMap(it -> Optionals.toStream(it))//
.findFirst());
}
/*
@@ -232,7 +231,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
public <A extends Annotation> Optional<A> findPropertyOrOwnerAnnotation(Class<A> annotationType) {
Optional<A> annotation = findAnnotation(annotationType);
return annotation.isPresent() ? annotation : owner.findAnnotation(annotationType);
return annotation.isPresent() ? annotation : getOwner().findAnnotation(annotationType);
}
/**
@@ -277,7 +276,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
public String toString() {
if (annotationCache.isEmpty()) {
populateAnnotationCache(field);
populateAnnotationCache(getProperty());
}
StringBuilder builder = new StringBuilder().append(annotationCache.values().stream()//
@@ -289,6 +288,6 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
}
private Stream<Optional<? extends AnnotatedElement>> getAccessors() {
return Arrays.<Optional<? extends AnnotatedElement>> asList(getGetter(), getSetter(), getField()).stream();
return Arrays.<Optional<? extends AnnotatedElement>>asList(getGetter(), getSetter(), getField()).stream();
}
}

View File

@@ -35,6 +35,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.mapping.Alias;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.IdentifierAccessor;
@@ -79,7 +80,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
private Optional<P> versionProperty = Optional.empty();
private PersistentPropertyAccessorFactory propertyAccessorFactory;
private final Lazy<Optional<? extends Object>> typeAlias;
private final Lazy<Alias> typeAlias;
/**
* Creates a new {@link BasicPersistentEntity} from the given {@link TypeInformation}.
@@ -106,16 +107,17 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
this.properties = new ArrayList<>();
this.comparator = comparator;
this.constructor = new PreferredConstructorDiscoverer<>(this).getConstructor();
this.associations = comparator.<Set<Association<P>>> map(it -> new TreeSet<>(new AssociationComparator<>(it)))
.orElse(new HashSet<>());
this.associations = comparator.<Set<Association<P>>>map(it -> new TreeSet<>(new AssociationComparator<>(it)))
.orElseGet(() -> new HashSet<>());
this.propertyCache = new HashMap<>();
this.annotationCache = new HashMap<>();
this.propertyAccessorFactory = BeanWrapperPropertyAccessorFactory.INSTANCE;
this.typeAlias = Lazy
.of(() -> Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(getType(), TypeAlias.class))//
.map(TypeAlias::value).filter(it -> StringUtils.hasText(it)));
this.typeAlias = Lazy.of(() -> Alias
.ofOptional(Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(getType(), TypeAlias.class))//
.map(TypeAlias::value)//
.filter(it -> StringUtils.hasText(it))));
}
/*
@@ -304,7 +306,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentEntity#getTypeAlias()
*/
public Optional<? extends Object> getTypeAlias() {
public Alias getTypeAlias() {
return typeAlias.get();
}
@@ -441,7 +443,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
* @see org.springframework.data.mapping.IdentifierAccessor#getIdentifier()
*/
@Override
public Optional<? extends Object> getIdentifier() {
public Optional<Object> getIdentifier() {
return Optional.empty();
}
}

View File

@@ -80,7 +80,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentPropertyAccessor#getProperty(org.springframework.data.mapping.PersistentProperty)
*/
public Optional<? extends Object> getProperty(PersistentProperty<?> property) {
public Optional<Object> getProperty(PersistentProperty<?> property) {
return getProperty(property, property.getType());
}

View File

@@ -33,7 +33,7 @@ enum BeanWrapperPropertyAccessorFactory implements PersistentPropertyAccessorFac
*/
@Override
public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean) {
return new BeanWrapper<Object>(bean);
return new BeanWrapper<>(bean);
}
/*

View File

@@ -53,7 +53,7 @@ public class CamelCaseSplittingFieldNamingStrategy implements FieldNamingStrateg
public String getFieldName(PersistentProperty<?> property) {
List<String> parts = ParsingUtils.splitCamelCaseToLower(property.getName());
List<String> result = new ArrayList<String>();
List<String> result = new ArrayList<>();
for (String part : parts) {

View File

@@ -64,9 +64,6 @@ import org.springframework.util.ReflectionUtils;
*/
public class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccessorFactory {
private static final boolean IS_JAVA_7_OR_BETTER = org.springframework.util.ClassUtils
.isPresent("java.lang.invoke.MethodHandle", ClassGeneratingPropertyAccessorFactory.class.getClassLoader());
private volatile Map<TypeInformation<?>, Class<PersistentPropertyAccessor>> propertyAccessorClasses = new HashMap<TypeInformation<?>, Class<PersistentPropertyAccessor>>(
32);
@@ -103,15 +100,11 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
Assert.notNull(entity, "PersistentEntity must not be null!");
if (!IS_JAVA_7_OR_BETTER) {
return false;
}
if (entity.getType().getClassLoader() == null || entity.getType().getPackage().getName().startsWith("java")) {
return false;
}
final Set<Integer> hashCodes = new HashSet<Integer>();
final Set<Integer> hashCodes = new HashSet<>();
final AtomicInteger propertyCount = new AtomicInteger();
entity.doWithProperties(new SimplePropertyHandler() {
@@ -821,7 +814,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
int[] hashes = new int[propertyStackMap.size()];
Label[] switchJumpLabels = new Label[propertyStackMap.size()];
List<PropertyStackAddress> stackmap = new ArrayList<PropertyStackAddress>(propertyStackMap.values());
List<PropertyStackAddress> stackmap = new ArrayList<>(propertyStackMap.values());
Collections.sort(stackmap);
for (int i = 0; i < stackmap.size(); i++) {
@@ -983,8 +976,8 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
mv.visitLocalVariable(THIS_REF, referenceName(internalClassName), null, l0, l1, 0);
mv.visitLocalVariable("property", "Lorg/springframework/data/mapping/PersistentProperty;",
"Lorg/springframework/data/mapping/PersistentProperty<*>;", l0, l1, 1);
mv.visitLocalVariable("optional", referenceName(JAVA_UTIL_OPTIONAL),
"Ljava/util/Optional<+Ljava/lang/Object;>;", l0, l1, 2);
mv.visitLocalVariable("optional", referenceName(JAVA_UTIL_OPTIONAL), "Ljava/util/Optional<+Ljava/lang/Object;>;",
l0, l1, 2);
if (isAccessible(entity)) {
mv.visitLocalVariable(BEAN_FIELD, referenceName(entity.getType()), null, l0, l1, 3);
@@ -1022,7 +1015,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
int[] hashes = new int[propertyStackMap.size()];
Label[] switchJumpLabels = new Label[propertyStackMap.size()];
List<PropertyStackAddress> stackmap = new ArrayList<PropertyStackAddress>(propertyStackMap.values());
List<PropertyStackAddress> stackmap = new ArrayList<>(propertyStackMap.values());
Collections.sort(stackmap);
for (int i = 0; i < stackmap.size(); i++) {

View File

@@ -65,7 +65,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
* @see org.springframework.data.mapping.PersistentPropertyAccessor#getProperty(org.springframework.data.mapping.PersistentProperty)
*/
@Override
public Optional<? extends Object> getProperty(PersistentProperty<?> property) {
public Optional<Object> getProperty(PersistentProperty<?> property) {
return accessor.getProperty(property);
}

View File

@@ -56,7 +56,7 @@ public class IdPropertyIdentifierAccessor implements IdentifierAccessor {
* (non-Javadoc)
* @see org.springframework.data.keyvalue.core.IdentifierAccessor#getIdentifier()
*/
public Optional<? extends Object> getIdentifier() {
return idProperty.map(it -> accessor.getProperty(it));
public Optional<Object> getIdentifier() {
return idProperty.flatMap(it -> accessor.getProperty(it));
}
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mapping.model;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Optional;
import org.springframework.data.util.Lazy;
import org.springframework.util.Assert;
/**
* @author Oliver Gierke
*/
@RequiredArgsConstructor
public class Property {
private final @Getter Optional<Field> field;
private final Optional<PropertyDescriptor> descriptor;
private final Lazy<Class<?>> rawType;
private final Lazy<Integer> hashCode;
private Property(Optional<Field> field, Optional<PropertyDescriptor> descriptor) {
this.field = field;
this.descriptor = descriptor;
this.hashCode = Lazy.of(() -> computeHashCode());
this.rawType = Lazy
.of(() -> field.<Class<?>>map(Field::getType).orElseGet(() -> descriptor.map(it -> it.getPropertyType())//
.orElseThrow(() -> new IllegalStateException())));
}
public static Property of(Field field) {
return of(field, Optional.empty());
}
public static Property of(Field field, Optional<PropertyDescriptor> descriptor) {
Assert.notNull(field, "Field must not be null!");
return new Property(Optional.of(field), descriptor);
}
public static Property of(PropertyDescriptor descriptor) {
Assert.notNull(descriptor, "PropertyDescriptor must not be null!");
return new Property(Optional.empty(), Optional.of(descriptor));
}
public boolean isFieldBacked() {
return field.isPresent();
}
public Optional<Method> getGetter() {
return descriptor.map(it -> it.getReadMethod())//
.filter(it -> getRawType().isAssignableFrom(it.getReturnType()));
}
public Optional<Method> getSetter() {
return descriptor.map(it -> it.getWriteMethod())//
.filter(it -> it.getParameterTypes()[0].isAssignableFrom(getRawType()));
}
/**
* @return
*/
public String getName() {
return field.map(Field::getName).orElseGet(() -> descriptor.map(it -> it.getName())//
.orElseThrow(() -> new IllegalStateException()));
}
public Class<?> getRawType() {
return rawType.get();
}
private int computeHashCode() {
return this.field.map(it -> it.hashCode())
.orElseGet(() -> this.descriptor.map(it -> it.hashCode()).orElseThrow(() -> new IllegalStateException()));
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return hashCode.get();
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Property)) {
return false;
}
Property that = (Property) obj;
return this.field.isPresent() ? this.field.equals(that.field) : this.descriptor.equals(that.descriptor);
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return field.map(Object::toString)
.orElseGet(() -> descriptor.map(Object::toString).orElseThrow(() -> new IllegalStateException()));
}
}

View File

@@ -62,13 +62,10 @@ public class SpELExpressionParameterValueProvider<P extends PersistentProperty<P
*/
public <T> Optional<T> getParameterValue(Parameter<T, P> parameter) {
if (!parameter.hasSpelExpression()) {
return delegate.getParameterValue(parameter);
}
Optional<Object> object = Optional.ofNullable(evaluator.evaluate(parameter.getSpelExpression().orElse(null)));
return object.map(it -> potentiallyConvertSpelValue(object, parameter));
return parameter.getSpelExpression()//
.map(it -> Optional.ofNullable(evaluator.evaluate(it))//
.map(result -> potentiallyConvertSpelValue(result, parameter)))
.orElseGet(() -> delegate.getParameterValue(parameter));
}
/**