DATACMNS-1101 - Reduce Optional usage in convert/mapping packages.
Reducing Optional usage that lies on hot code paths for object mapping.
This commit is contained in:
committed by
Oliver Gierke
parent
4aa083377b
commit
74fbe13f54
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -15,33 +15,39 @@
|
||||
*/
|
||||
package org.springframework.data.mapping;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Interface for a component allowing the access of identifier values.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @see TargetAwareIdentifierAccessor
|
||||
*/
|
||||
public interface IdentifierAccessor {
|
||||
|
||||
/**
|
||||
* Returns the value of the identifier.
|
||||
*
|
||||
*
|
||||
* @return the identifier of the underlying instance.
|
||||
*/
|
||||
Optional<Object> getIdentifier();
|
||||
Object getIdentifier();
|
||||
|
||||
/**
|
||||
* Returns the identifier of the underlying instance. Implementations are strongly recommended to extends either
|
||||
* {@link TargetAwareIdentifierAccessor} or override this method to add more context to the exception being thrown in
|
||||
* case of the absence of an identifier.
|
||||
*
|
||||
*
|
||||
* @return the identifier of the underlying instance
|
||||
* @throws IllegalStateException in case no identifier could be retrieved.
|
||||
* @since 2.0
|
||||
*/
|
||||
default Object getRequiredIdentifier() {
|
||||
return getIdentifier().orElseThrow(() -> new IllegalStateException(String.format("Could not obtain identifier!")));
|
||||
|
||||
Object identifier = getIdentifier();
|
||||
|
||||
if (identifier != null) {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Could not obtain identifier!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -15,15 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.mapping;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
|
||||
/**
|
||||
* Domain service to allow accessing and setting {@link PersistentProperty}s of an entity. Usually obtained through
|
||||
* {@link PersistentEntity#getPropertyAccessor(Object)}. In case type conversion shall be applied on property access,
|
||||
* use a {@link ConvertingPropertyAccessor}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 1.10
|
||||
* @see PersistentEntity#getPropertyAccessor(Object)
|
||||
@@ -34,26 +32,25 @@ public interface PersistentPropertyAccessor {
|
||||
/**
|
||||
* Sets the given {@link PersistentProperty} to the given value. Will do type conversion if a
|
||||
* {@link org.springframework.core.convert.ConversionService} is configured.
|
||||
*
|
||||
*
|
||||
* @param property must not be {@literal null}.
|
||||
* @param value can be {@literal null}.
|
||||
* @throws org.springframework.data.mapping.model.MappingException in case an exception occurred when setting the
|
||||
* property value.
|
||||
*/
|
||||
void setProperty(PersistentProperty<?> property, Optional<? extends Object> value);
|
||||
void setProperty(PersistentProperty<?> property, Object value);
|
||||
|
||||
/**
|
||||
* Returns the value of the given {@link PersistentProperty} of the underlying bean instance.
|
||||
*
|
||||
* @param <S>
|
||||
*
|
||||
* @param property must not be {@literal null}.
|
||||
* @return can be {@literal null}.
|
||||
*/
|
||||
Optional<Object> getProperty(PersistentProperty<?> property);
|
||||
Object getProperty(PersistentProperty<?> property);
|
||||
|
||||
/**
|
||||
* Returns the underlying bean.
|
||||
*
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
Object getBean();
|
||||
|
||||
@@ -22,8 +22,9 @@ import java.util.function.Supplier;
|
||||
/**
|
||||
* {@link IdentifierAccessor} that is aware of the target bean to obtain the identifier from so that it can generate a
|
||||
* more meaningful exception in case of an absent identifier and a call to {@link #getRequiredIdentifier()}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @since 2.0
|
||||
* @soundtrack Anika Nilles - Greenfield (Pikalar)
|
||||
*/
|
||||
@@ -32,13 +33,19 @@ public abstract class TargetAwareIdentifierAccessor implements IdentifierAccesso
|
||||
|
||||
private final Supplier<Object> target;
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.IdentifierAccessor#getRequiredIdentifier()
|
||||
*/
|
||||
@Override
|
||||
public Object getRequiredIdentifier() {
|
||||
return getIdentifier().orElseThrow(
|
||||
() -> new IllegalStateException(String.format("Could not obtain identifier from %s!", target.get())));
|
||||
|
||||
Object identifier = getIdentifier();
|
||||
|
||||
if (identifier != null) {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
throw new IllegalStateException(String.format("Could not obtain identifier from %s!", target.get()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ import org.springframework.util.StringUtils;
|
||||
* The implementation uses a {@link ReentrantReadWriteLock} to make sure {@link PersistentEntity} are completely
|
||||
* populated before accessing them from outside.
|
||||
*
|
||||
* @param E the concrete {@link PersistentEntity} type the {@link MappingContext} implementation creates
|
||||
* @param P the concrete {@link PersistentProperty} type the {@link MappingContext} implementation creates
|
||||
* @param <E> the concrete {@link PersistentEntity} type the {@link MappingContext} implementation creates
|
||||
* @param <P> the concrete {@link PersistentProperty} type the {@link MappingContext} implementation creates
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
* @author Michael Hunger
|
||||
@@ -164,7 +164,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
return getPersistentEntity(ClassTypeInformation.from(type));
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.context.MappingContext#getRequiredPersistentEntity(java.lang.Class)
|
||||
*/
|
||||
@@ -228,7 +228,7 @@ 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)
|
||||
*/
|
||||
@@ -251,7 +251,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
return getPersistentEntity(typeInfo.getActualType());
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.context.MappingContext#getRequiredPersistentEntity(org.springframework.data.mapping.PersistentProperty)
|
||||
*/
|
||||
@@ -457,8 +457,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
/**
|
||||
* Creates the concrete instance of {@link PersistentProperty}.
|
||||
*
|
||||
* @param field
|
||||
* @param descriptor
|
||||
* @param property
|
||||
* @param owner
|
||||
* @param simpleTypeHolder
|
||||
* @return
|
||||
@@ -606,7 +605,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
/**
|
||||
* Returns whether the given {@link PropertyDescriptor} is one to create a {@link PersistentProperty} for.
|
||||
*
|
||||
* @param descriptor must not be {@literal null}.
|
||||
* @param property must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public boolean matches(Property property) {
|
||||
@@ -650,7 +649,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
/**
|
||||
* Returns whether the given {@link Field} matches the defined {@link PropertyMatch}.
|
||||
*
|
||||
* @param field must not be {@literal null}.
|
||||
* @param name must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public boolean matches(String name, Class<?> type) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
* Copyright 2011-2017 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.
|
||||
@@ -27,35 +27,44 @@ import org.springframework.data.util.TypeInformation;
|
||||
* This interface defines the overall context including all known PersistentEntity instances and methods to obtain
|
||||
* instances on demand. it is used internally to establish associations between entities and also at runtime to obtain
|
||||
* entities by name.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Jon Brisbin
|
||||
* @author Graeme Rocher
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface MappingContext<E extends PersistentEntity<?, P>, P extends PersistentProperty<P>> {
|
||||
|
||||
/**
|
||||
* Returns all {@link PersistentEntity}s held in the context.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Collection<E> getPersistentEntities();
|
||||
|
||||
/**
|
||||
* Returns a {@link PersistentEntity} for the given {@link Class}. Will return {@literal null} for types that are
|
||||
* considered simple ones.
|
||||
*
|
||||
* Returns a {@link PersistentEntity} for the given {@link Class}. Will return {@link Optional#empty()} for types that
|
||||
* are considered simple ones.
|
||||
*
|
||||
* @see org.springframework.data.mapping.model.SimpleTypeHolder#isSimpleType(Class)
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Optional<E> getPersistentEntity(Class<?> type);
|
||||
|
||||
/**
|
||||
* Returns a required {@link PersistentEntity} for the given {@link Class}. Will throw
|
||||
* {@link IllegalArgumentException} for types that are considered simple ones.
|
||||
*
|
||||
* @see org.springframework.data.mapping.model.SimpleTypeHolder#isSimpleType(Class)
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
E getRequiredPersistentEntity(Class<?> type);
|
||||
|
||||
/**
|
||||
* Returns whether the {@link MappingContext} currently contains a {@link PersistentEntity} for the type.
|
||||
*
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
* @since 1.8
|
||||
@@ -63,20 +72,28 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
|
||||
boolean hasPersistentEntityFor(Class<?> type);
|
||||
|
||||
/**
|
||||
* Returns a {@link PersistentEntity} for the given {@link TypeInformation}. Will return {@literal null} for types
|
||||
* that are considered simple ones.
|
||||
*
|
||||
* Returns a {@link PersistentEntity} for the given {@link TypeInformation}. Will return {@link Optional#empty()} for
|
||||
* types that are considered simple ones.
|
||||
*
|
||||
* @see org.springframework.data.mapping.model.SimpleTypeHolder#isSimpleType(Class)
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Optional<E> getPersistentEntity(TypeInformation<?> type);
|
||||
|
||||
/**
|
||||
* Returns a {@link PersistentEntity} for the given {@link TypeInformation}. Will throw
|
||||
* {@link IllegalArgumentException} for types that are considered simple ones.
|
||||
*
|
||||
* @see org.springframework.data.mapping.model.SimpleTypeHolder#isSimpleType(Class)
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
E getRequiredPersistentEntity(TypeInformation<?> type);
|
||||
|
||||
/**
|
||||
* Returns the {@link PersistentEntity} mapped by the given {@link 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
|
||||
@@ -85,11 +102,20 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
|
||||
*/
|
||||
Optional<E> getPersistentEntity(P persistentProperty);
|
||||
|
||||
/**
|
||||
* Returns the {@link PersistentEntity} mapped by the given {@link 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 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
|
||||
@@ -99,7 +125,7 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
|
||||
|
||||
/**
|
||||
* Returns all {@link PersistentProperty}s for the given dot path notation based on the given type.
|
||||
*
|
||||
*
|
||||
* @param propertyPath must not be {@literal null}.
|
||||
* @param type must not be {@literal null}.
|
||||
* @return the {@link PersistentPropertyPath} representing the given property path on the given type.
|
||||
@@ -110,7 +136,7 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
|
||||
/**
|
||||
* 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}.
|
||||
@@ -120,7 +146,7 @@ public interface MappingContext<E extends PersistentEntity<?, P>, P extends Pers
|
||||
|
||||
/**
|
||||
* Returns the {@link TypeInformation}s for all {@link PersistentEntity}s in the {@link MappingContext}.
|
||||
*
|
||||
*
|
||||
* @return all {@link TypeInformation}s for the {@link PersistentEntity}s in the {@link MappingContext}.
|
||||
* @since 1.8
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2015 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.
|
||||
@@ -33,11 +33,11 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* An {@link IsNewStrategyFactory} using a {@link MappingContext} to determine the {@link IsNewStrategy} to be returned
|
||||
* for a particular type. It will look for a version and id property on the {@link PersistentEntity} and return a
|
||||
* strategy instance that will refelctively inspect the property for {@literal null} values or {@literal null} or a
|
||||
* strategy instance that will reflectively inspect the property for {@literal null} values or {@literal null} or a
|
||||
* value of 0 in case of a version property.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupport {
|
||||
|
||||
@@ -45,7 +45,7 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingContextIsNewStrategyFactory} using the given {@link MappingContext}.
|
||||
*
|
||||
*
|
||||
* @param context must not be {@literal null}.
|
||||
* @deprecated use {@link MappingContextIsNewStrategyFactory(PersistentEntities)} instead.
|
||||
*/
|
||||
@@ -56,8 +56,8 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingContextIsNewStrategyFactory} using the given {@link PersistentEntities}.
|
||||
*
|
||||
* @param context must not be {@literal null}.
|
||||
*
|
||||
* @param entities must not be {@literal null}.
|
||||
* @since 1.10
|
||||
*/
|
||||
public MappingContextIsNewStrategyFactory(PersistentEntities entities) {
|
||||
@@ -74,11 +74,11 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp
|
||||
protected IsNewStrategy doGetIsNewStrategy(Class<?> type) {
|
||||
|
||||
return context.getPersistentEntity(type)//
|
||||
.flatMap(MappingContextIsNewStrategyFactory::foo)//
|
||||
.flatMap(MappingContextIsNewStrategyFactory::getIsNewStrategy)//
|
||||
.orElseThrow(() -> new MappingException(String.format("Cannot determine IsNewStrategy for type %s!", type)));
|
||||
}
|
||||
|
||||
private static Optional<IsNewStrategy> foo(PersistentEntity<?, ?> entity) {
|
||||
private static Optional<IsNewStrategy> getIsNewStrategy(PersistentEntity<?, ?> entity) {
|
||||
|
||||
if (entity.hasVersionProperty()) {
|
||||
|
||||
@@ -96,15 +96,15 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp
|
||||
|
||||
/**
|
||||
* {@link IsNewStrategy} implementation that will inspect a given {@link PersistentProperty} and call
|
||||
* {@link #decideIsNew(Object)} with the value retrieved by reflection.
|
||||
*
|
||||
* {@link #isNew(Object)} with the value retrieved by reflection.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor(staticName = "of")
|
||||
static class PersistentPropertyInspectingIsNewStrategy implements IsNewStrategy {
|
||||
|
||||
private final @NonNull PersistentProperty<?> property;
|
||||
private final @NonNull Function<Optional<Object>, Boolean> isNew;
|
||||
private final @NonNull Function<Object, Boolean> isNew;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -119,20 +119,11 @@ public class MappingContextIsNewStrategyFactory extends IsNewStrategyFactorySupp
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean propertyIsNull(Optional<Object> it) {
|
||||
return !it.isPresent();
|
||||
private static boolean propertyIsNull(Object it) {
|
||||
return it == null;
|
||||
}
|
||||
|
||||
private static boolean propertyIsNullOrZeroNumber(Optional<Object> it) {
|
||||
|
||||
return it.map(value -> {
|
||||
|
||||
if (!(value instanceof Number)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((Number) value).longValue() == 0;
|
||||
|
||||
}).orElse(true);
|
||||
private static boolean propertyIsNullOrZeroNumber(Object value) {
|
||||
return propertyIsNull(value) || value instanceof Number && ((Number) value).longValue() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,11 +36,12 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Simple impementation of {@link PersistentProperty}.
|
||||
*
|
||||
* Simple implementation of {@link PersistentProperty}.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>> implements PersistentProperty<P> {
|
||||
|
||||
@@ -121,7 +122,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
return information;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentProperty#getPersistentEntityType()
|
||||
*/
|
||||
@@ -133,11 +134,11 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
}
|
||||
|
||||
return entityTypeInformation.get()//
|
||||
.map(it -> Collections.singleton(it))//
|
||||
.orElseGet(() -> Collections.emptySet());
|
||||
.map(Collections::singleton)//
|
||||
.orElseGet(Collections::emptySet);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentProperty#getGetter()
|
||||
*/
|
||||
@@ -146,7 +147,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
return property.getGetter();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentProperty#getSetter()
|
||||
*/
|
||||
@@ -268,7 +269,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
return isMap() ? information.getMapValueType().map(TypeInformation::getType) : Optional.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentProperty#getActualType()
|
||||
*/
|
||||
@@ -277,7 +278,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
return information.getActualType().getType();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess()
|
||||
*/
|
||||
@@ -285,7 +286,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
return usePropertyAccess.get();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@@ -305,7 +306,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
return this.property.equals(that.property);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@@ -314,7 +315,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
return this.hashCode.get();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.mapping.model;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -99,7 +98,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
|
||||
annotationType.getSimpleName(), getName(), getOwner().getType().getSimpleName());
|
||||
|
||||
annotationCache.put(annotationType,
|
||||
Optional.of(AnnotatedElementUtils.findMergedAnnotation(it, annotationType)));
|
||||
Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(it, annotationType)));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -114,7 +113,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
|
||||
annotationType.getSimpleName(), it.getName(), getOwner().getType().getSimpleName());
|
||||
|
||||
annotationCache.put(annotationType,
|
||||
Optional.of(AnnotatedElementUtils.findMergedAnnotation(it, annotationType)));
|
||||
Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(it, annotationType)));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -156,7 +155,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
|
||||
* Considers plain transient fields, fields annotated with {@link Transient}, {@link Value} or {@link Autowired} as
|
||||
* transient.
|
||||
*
|
||||
* @see org.springframework.data.mapping.BasicPersistentProperty#isTransient()
|
||||
* @see org.springframework.data.mapping.PersistentProperty#isTransient()
|
||||
*/
|
||||
@Override
|
||||
public boolean isTransient() {
|
||||
@@ -239,10 +238,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
|
||||
*/
|
||||
private <A extends Annotation> Optional<A> cacheAndReturn(Class<? extends A> type, Optional<A> annotation) {
|
||||
|
||||
if (annotationCache != null) {
|
||||
annotationCache.put(type, annotation);
|
||||
}
|
||||
|
||||
annotationCache.put(type, annotation);
|
||||
return annotation;
|
||||
}
|
||||
|
||||
@@ -277,7 +273,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
|
||||
}
|
||||
|
||||
String builder = annotationCache.values().stream() //
|
||||
.flatMap(it -> Optionals.toStream(it)) //
|
||||
.flatMap(Optionals::toStream) //
|
||||
.map(Object::toString) //
|
||||
.collect(Collectors.joining(" "));
|
||||
|
||||
@@ -285,6 +281,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 Stream.of(getGetter(), getSetter(), getField());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,18 +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;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.PreferredConstructor;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.SimpleAssociationHandler;
|
||||
import org.springframework.data.mapping.SimplePropertyHandler;
|
||||
import org.springframework.data.mapping.TargetAwareIdentifierAccessor;
|
||||
import org.springframework.data.mapping.*;
|
||||
import org.springframework.data.util.Lazy;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -74,7 +63,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
private final Optional<Comparator<P>> comparator;
|
||||
private final Set<Association<P>> associations;
|
||||
|
||||
private final Map<String, P> propertyCache;
|
||||
private final Map<String, Optional<P>> propertyCache;
|
||||
private final Map<Class<? extends Annotation>, Optional<Annotation>> annotationCache;
|
||||
|
||||
private Optional<P> idProperty = Optional.empty();
|
||||
@@ -208,7 +197,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
properties.add(property);
|
||||
|
||||
if (!propertyCache.containsKey(property.getName())) {
|
||||
propertyCache.put(property.getName(), property);
|
||||
propertyCache.put(property.getName(), Optional.of(property));
|
||||
}
|
||||
|
||||
P candidate = returnPropertyIfBetterIdPropertyCandidateOrNull(property);
|
||||
@@ -268,7 +257,14 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
* @see org.springframework.data.mapping.PersistentEntity#getPersistentProperty(java.lang.String)
|
||||
*/
|
||||
public Optional<P> getPersistentProperty(String name) {
|
||||
return Optional.ofNullable(propertyCache.get(name));
|
||||
|
||||
Optional<P> property = propertyCache.get(name);
|
||||
|
||||
if (property != null) {
|
||||
return property;
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -467,8 +463,8 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
* @see org.springframework.data.mapping.IdentifierAccessor#getIdentifier()
|
||||
*/
|
||||
@Override
|
||||
public Optional<Object> getIdentifier() {
|
||||
return Optional.empty();
|
||||
public Object getIdentifier() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
* Copyright 2011-2017 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,8 +26,9 @@ import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Domain service to allow accessing the values of {@link PersistentProperty}s on a given bean.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class BeanWrapper<T> implements PersistentPropertyAccessor {
|
||||
|
||||
@@ -35,7 +36,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
|
||||
|
||||
/**
|
||||
* Creates a new {@link BeanWrapper} for the given bean.
|
||||
*
|
||||
*
|
||||
* @param bean must not be {@literal null}.
|
||||
*/
|
||||
protected BeanWrapper(T bean) {
|
||||
@@ -48,7 +49,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentPropertyAccessor#setProperty(org.springframework.data.mapping.PersistentProperty, java.util.Optional)
|
||||
*/
|
||||
public void setProperty(PersistentProperty<?> property, Optional<? extends Object> value) {
|
||||
public void setProperty(PersistentProperty<?> property, Object value) {
|
||||
|
||||
Assert.notNull(property, "PersistentProperty must not be null!");
|
||||
|
||||
@@ -59,7 +60,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
|
||||
Field field = property.getField().get();
|
||||
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
ReflectionUtils.setField(field, bean, value.orElse(null));
|
||||
ReflectionUtils.setField(field, bean, value);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -68,7 +69,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
|
||||
setter.ifPresent(it -> {
|
||||
|
||||
ReflectionUtils.makeAccessible(it);
|
||||
ReflectionUtils.invokeMethod(it, bean, value.orElse(null));
|
||||
ReflectionUtils.invokeMethod(it, bean, value);
|
||||
});
|
||||
|
||||
} catch (IllegalStateException e) {
|
||||
@@ -80,13 +81,13 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentPropertyAccessor#getProperty(org.springframework.data.mapping.PersistentProperty)
|
||||
*/
|
||||
public Optional<Object> getProperty(PersistentProperty<?> property) {
|
||||
public Object getProperty(PersistentProperty<?> property) {
|
||||
return getProperty(property, property.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the given {@link PersistentProperty} potentially converted to the given type.
|
||||
*
|
||||
*
|
||||
* @param <S>
|
||||
* @param property must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
@@ -94,7 +95,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
|
||||
* @throws MappingException in case an exception occured when accessing the property.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <S> Optional<S> getProperty(PersistentProperty<?> property, Class<? extends S> type) {
|
||||
public <S> Object getProperty(PersistentProperty<?> property, Class<? extends S> type) {
|
||||
|
||||
Assert.notNull(property, "PersistentProperty must not be null!");
|
||||
|
||||
@@ -104,7 +105,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
|
||||
|
||||
Field field = property.getField().get();
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
return Optional.ofNullable((S) ReflectionUtils.getField(field, bean));
|
||||
return ReflectionUtils.getField(field, bean);
|
||||
}
|
||||
|
||||
Optional<Method> getter = property.getGetter();
|
||||
@@ -113,7 +114,7 @@ class BeanWrapper<T> implements PersistentPropertyAccessor {
|
||||
|
||||
ReflectionUtils.makeAccessible(it);
|
||||
return (S) ReflectionUtils.invokeMethod(it, bean);
|
||||
});
|
||||
}).orElse(null);
|
||||
|
||||
} catch (IllegalStateException e) {
|
||||
throw new MappingException(
|
||||
|
||||
@@ -260,7 +260,6 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
|
||||
private static final String JAVA_LANG_REFLECT_METHOD = "java/lang/reflect/Method";
|
||||
private static final String JAVA_LANG_INVOKE_METHOD_HANDLE = "java/lang/invoke/MethodHandle";
|
||||
private static final String JAVA_LANG_CLASS = "java/lang/Class";
|
||||
private static final String JAVA_UTIL_OPTIONAL = "java/util/Optional";
|
||||
private static final String BEAN_FIELD = "bean";
|
||||
private static final String THIS_REF = "this";
|
||||
private static final String PERSISTENT_PROPERTY = "org/springframework/data/mapping/PersistentProperty";
|
||||
@@ -707,8 +706,8 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
|
||||
List<PersistentProperty<?>> persistentProperties, String internalClassName, ClassWriter cw) {
|
||||
|
||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getProperty",
|
||||
"(Lorg/springframework/data/mapping/PersistentProperty;)Ljava/util/Optional;",
|
||||
"(Lorg/springframework/data/mapping/PersistentProperty<*>;)Ljava/util/Optional<+Ljava/lang/Object;>;", null);
|
||||
"(Lorg/springframework/data/mapping/PersistentProperty;)Ljava/lang/Object;",
|
||||
"(Lorg/springframework/data/mapping/PersistentProperty<*>;)Ljava/lang/Object;", null);
|
||||
mv.visitCode();
|
||||
|
||||
Label l0 = new Label();
|
||||
@@ -849,13 +848,11 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
|
||||
return null;
|
||||
});
|
||||
|
||||
mv.visitMethodInsn(INVOKESTATIC, JAVA_UTIL_OPTIONAL, "ofNullable",
|
||||
String.format("(%s)%s", referenceName(JAVA_LANG_OBJECT), referenceName(JAVA_UTIL_OPTIONAL)), false);
|
||||
mv.visitInsn(ARETURN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the {@link PersistentPropertyAccessor#setProperty(PersistentProperty, Optional)} method. *
|
||||
* Generate the {@link PersistentPropertyAccessor#setProperty(PersistentProperty, Object)} method. *
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
@@ -878,15 +875,14 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
|
||||
List<PersistentProperty<?>> persistentProperties, String internalClassName, ClassWriter cw) {
|
||||
|
||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "setProperty",
|
||||
"(Lorg/springframework/data/mapping/PersistentProperty;Ljava/util/Optional;)V",
|
||||
"(Lorg/springframework/data/mapping/PersistentProperty<*>;Ljava/util/Optional<+Ljava/lang/Object;>)V", null);
|
||||
"(Lorg/springframework/data/mapping/PersistentProperty;Ljava/lang/Object;)V",
|
||||
"(Lorg/springframework/data/mapping/PersistentProperty<*>;Ljava/lang/Object;)V", null);
|
||||
mv.visitCode();
|
||||
|
||||
Label l0 = new Label();
|
||||
mv.visitLabel(l0);
|
||||
|
||||
visitAssertNotNull(mv);
|
||||
visitUnwrapValue(mv);
|
||||
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
|
||||
@@ -908,8 +904,7 @@ 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("value", referenceName(JAVA_LANG_OBJECT), null, l0, l1, 2);
|
||||
|
||||
if (isAccessible(entity)) {
|
||||
mv.visitLocalVariable(BEAN_FIELD, referenceName(entity.getType()), null, l0, l1, 3);
|
||||
@@ -917,21 +912,10 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
|
||||
mv.visitLocalVariable(BEAN_FIELD, referenceName(JAVA_LANG_OBJECT), null, l0, l1, 3);
|
||||
}
|
||||
|
||||
mv.visitLocalVariable("value", referenceName(JAVA_LANG_OBJECT), null, l0, l1, 4);
|
||||
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private static void visitUnwrapValue(MethodVisitor mv) {
|
||||
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitInsn(ACONST_NULL);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, JAVA_UTIL_OPTIONAL, "orElse",
|
||||
String.format("(%s)%s", referenceName(JAVA_LANG_OBJECT), referenceName(JAVA_LANG_OBJECT)), false);
|
||||
mv.visitVarInsn(ASTORE, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the {@code switch(hashcode) {label: }} block.
|
||||
*/
|
||||
@@ -991,13 +975,13 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
|
||||
mv.visitFieldInsn(GETSTATIC, internalClassName, setterName(property),
|
||||
referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE));
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
mv.visitVarInsn(ALOAD, 4);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, JAVA_LANG_INVOKE_METHOD_HANDLE, "invoke",
|
||||
String.format("(%s%s)V", referenceName(JAVA_LANG_OBJECT), referenceName(JAVA_LANG_OBJECT)), false);
|
||||
} else {
|
||||
// bean.set...(object)
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
mv.visitVarInsn(ALOAD, 4);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
|
||||
Class<?> parameterType = it.getParameterTypes()[0];
|
||||
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(autoboxType(parameterType)));
|
||||
@@ -1025,13 +1009,13 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
|
||||
mv.visitFieldInsn(GETSTATIC, internalClassName, fieldSetterName(property),
|
||||
referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE));
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
mv.visitVarInsn(ALOAD, 4);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, JAVA_LANG_INVOKE_METHOD_HANDLE, "invoke",
|
||||
String.format("(%s%s)V", referenceName(JAVA_LANG_OBJECT), referenceName(JAVA_LANG_OBJECT)), false);
|
||||
} else {
|
||||
// bean.field
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
mv.visitVarInsn(ALOAD, 4);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
|
||||
Class<?> fieldType = it.getType();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
@@ -27,8 +25,9 @@ import org.springframework.util.Assert;
|
||||
* {@link #setProperty(PersistentProperty, Object)} to the type of the {@link PersistentProperty} using a
|
||||
* {@link ConversionService}. Exposes {@link #getProperty(PersistentProperty, Class)} to allow obtaining the value of a
|
||||
* property in a type the {@link ConversionService} can convert the raw type to.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
|
||||
|
||||
@@ -38,7 +37,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
|
||||
/**
|
||||
* Creates a new {@link ConvertingPropertyAccessor} for the given delegate {@link PersistentPropertyAccessor} and
|
||||
* {@link ConversionService}.
|
||||
*
|
||||
*
|
||||
* @param accessor must not be {@literal null}.
|
||||
* @param conversionService must not be {@literal null}.
|
||||
*/
|
||||
@@ -51,32 +50,32 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentPropertyAccessor#setProperty(org.springframework.data.mapping.PersistentProperty, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void setProperty(PersistentProperty<?> property, Optional<? extends Object> value) {
|
||||
public void setProperty(PersistentProperty<?> property, Object value) {
|
||||
accessor.setProperty(property, convertIfNecessary(value, property.getType()));
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentPropertyAccessor#getProperty(org.springframework.data.mapping.PersistentProperty)
|
||||
*/
|
||||
@Override
|
||||
public Optional<Object> getProperty(PersistentProperty<?> property) {
|
||||
public Object getProperty(PersistentProperty<?> property) {
|
||||
return accessor.getProperty(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the given {@link PersistentProperty} converted to the given type.
|
||||
*
|
||||
*
|
||||
* @param property must not be {@literal null}.
|
||||
* @param targetType must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public <T> Optional<T> getProperty(PersistentProperty<?> property, Class<T> targetType) {
|
||||
public <T> T getProperty(PersistentProperty<?> property, Class<T> targetType) {
|
||||
|
||||
Assert.notNull(property, "PersistentProperty must not be null!");
|
||||
Assert.notNull(targetType, "Target type must not be null!");
|
||||
@@ -84,7 +83,7 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
|
||||
return convertIfNecessary(getProperty(property), targetType);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentPropertyAccessor#getBean()
|
||||
*/
|
||||
@@ -96,13 +95,14 @@ public class ConvertingPropertyAccessor implements PersistentPropertyAccessor {
|
||||
/**
|
||||
* Triggers the conversion of the source value into the target type unless the value already is a value of given
|
||||
* target type.
|
||||
*
|
||||
*
|
||||
* @param source can be {@literal null}.
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Optional<T> convertIfNecessary(Optional<? extends Object> source, Class<T> type) {
|
||||
return source.map(it -> type.isAssignableFrom(it.getClass()) ? (T) it : conversionService.convert(it, type));
|
||||
private <T> T convertIfNecessary(Object source, Class<T> type) {
|
||||
return (T) (source == null ? null
|
||||
: type.isAssignableFrom(source.getClass()) ? source : conversionService.convert(source, type));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.mapping.IdentifierAccessor;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
@@ -26,7 +24,7 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link IdentifierAccessor}.
|
||||
*
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
* @since 1.10
|
||||
@@ -39,7 +37,7 @@ public class IdPropertyIdentifierAccessor extends TargetAwareIdentifierAccessor
|
||||
/**
|
||||
* Creates a new {@link IdPropertyIdentifierAccessor} for the given {@link PersistentEntity} and
|
||||
* {@link ConvertingPropertyAccessor}.
|
||||
*
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param target must not be {@literal null}.
|
||||
*/
|
||||
@@ -59,7 +57,7 @@ public class IdPropertyIdentifierAccessor extends TargetAwareIdentifierAccessor
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.keyvalue.core.IdentifierAccessor#getIdentifier()
|
||||
*/
|
||||
public Optional<Object> getIdentifier() {
|
||||
public Object getIdentifier() {
|
||||
return accessor.getProperty(idProperty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,20 +16,21 @@
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PreferredConstructor;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Exception being thrown in case an entity could not be instantiated in the process of a to-object-mapping.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Jon Brisbin
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class MappingInstantiationException extends RuntimeException {
|
||||
|
||||
@@ -43,43 +44,58 @@ public class MappingInstantiationException extends RuntimeException {
|
||||
/**
|
||||
* Creates a new {@link MappingInstantiationException} for the given {@link PersistentEntity}, constructor arguments
|
||||
* and the causing exception.
|
||||
*
|
||||
*
|
||||
* @param entity
|
||||
* @param arguments
|
||||
* @param cause
|
||||
*/
|
||||
public MappingInstantiationException(Optional<PersistentEntity<?, ?>> entity, List<Object> arguments,
|
||||
Exception cause) {
|
||||
this(entity, arguments, null, cause);
|
||||
public MappingInstantiationException(PersistentEntity<?, ?> entity, List<Object> arguments, Exception cause) {
|
||||
this(Optional.ofNullable(entity), arguments, null, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingInstantiationException} for the given constructor arguments and the causing exception.
|
||||
*
|
||||
* @param arguments
|
||||
* @param cause
|
||||
*/
|
||||
public MappingInstantiationException(List<Object> arguments, Exception cause) {
|
||||
this(Optional.empty(), arguments, null, cause);
|
||||
}
|
||||
|
||||
private MappingInstantiationException(Optional<PersistentEntity<?, ?>> entity, List<Object> arguments, String message,
|
||||
Exception cause) {
|
||||
|
||||
super(buildExceptionMessage(entity, arguments.stream(), message), cause);
|
||||
super(buildExceptionMessage(entity, arguments, message), cause);
|
||||
|
||||
this.entityType = entity.map(PersistentEntity::getType).orElse(null);
|
||||
this.constructor = entity.flatMap(PersistentEntity::getPersistenceConstructor).map(PreferredConstructor::getConstructor).orElse(null);
|
||||
this.constructor = entity.flatMap(PersistentEntity::getPersistenceConstructor)
|
||||
.map(PreferredConstructor::getConstructor).orElse(null);
|
||||
this.constructorArguments = arguments;
|
||||
}
|
||||
|
||||
private static String buildExceptionMessage(Optional<PersistentEntity<?, ?>> entity, Stream<Object> arguments,
|
||||
String defaultMessage) {
|
||||
private static String buildExceptionMessage(Optional<PersistentEntity<?, ?>> entity, List<Object> arguments,
|
||||
String defaultMessage) {
|
||||
|
||||
return entity.map(it -> {
|
||||
|
||||
Optional<? extends PreferredConstructor<?, ?>> constructor = it.getPersistenceConstructor();
|
||||
|
||||
List<String> toStringArgs = new ArrayList<>(arguments.size());
|
||||
for (Object o : arguments) {
|
||||
toStringArgs.add(ObjectUtils.nullSafeToString(o));
|
||||
}
|
||||
|
||||
return String.format(TEXT_TEMPLATE, it.getType().getName(),
|
||||
constructor.map(c -> c.getConstructor().toString()).orElse("NO_CONSTRUCTOR"),
|
||||
String.join(",", arguments.map(Object::toString).collect(Collectors.toList())));
|
||||
constructor.map(c -> c.getConstructor().toString()).orElse("NO_CONSTRUCTOR"), //
|
||||
String.join(",", toStringArgs));
|
||||
|
||||
}).orElse(defaultMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the entity that was attempted to instantiate.
|
||||
*
|
||||
*
|
||||
* @return the entityType
|
||||
*/
|
||||
public Optional<Class<?>> getEntityType() {
|
||||
@@ -88,7 +104,7 @@ public class MappingInstantiationException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* The constructor used during the instantiation attempt.
|
||||
*
|
||||
*
|
||||
* @return the constructor
|
||||
*/
|
||||
public Optional<Constructor<?>> getConstructor() {
|
||||
@@ -97,7 +113,7 @@ public class MappingInstantiationException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* The constructor arguments used to invoke the constructor.
|
||||
*
|
||||
*
|
||||
* @return the constructorArguments
|
||||
*/
|
||||
public List<Object> getConstructorArguments() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2012 by the original author(s).
|
||||
* Copyright (c) 2011-2017 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,23 +15,21 @@
|
||||
*/
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PreferredConstructor.Parameter;
|
||||
|
||||
/**
|
||||
* Callback interface to lookup values for a given {@link Parameter}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface ParameterValueProvider<P extends PersistentProperty<P>> {
|
||||
|
||||
/**
|
||||
* Returns the value to be used for the given {@link Parameter} (usually when entity instances are created).
|
||||
*
|
||||
*
|
||||
* @param parameter must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
<T> Optional<T> getParameterValue(Parameter<T, P> parameter);
|
||||
<T> T getParameterValue(Parameter<T, P> parameter);
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PreferredConstructor;
|
||||
@@ -28,31 +26,29 @@ import org.springframework.util.Assert;
|
||||
* the value of the property referenced by the given {@link Parameter}. Additionally a
|
||||
* {@link DefaultSpELExpressionEvaluator} can be configured to get property value resolution trumped by a SpEL
|
||||
* expression evaluation.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class PersistentEntityParameterValueProvider<P extends PersistentProperty<P>>
|
||||
implements ParameterValueProvider<P> {
|
||||
|
||||
private final PersistentEntity<?, P> entity;
|
||||
private final PropertyValueProvider<P> provider;
|
||||
private final Optional<Object> parent;
|
||||
private final Object parent;
|
||||
|
||||
/**
|
||||
* Creates a new {@link PersistentEntityParameterValueProvider} for the given {@link PersistentEntity} and
|
||||
* {@link PropertyValueProvider}.
|
||||
*
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param provider must not be {@literal null}.
|
||||
* @param parent the parent object being created currently, can be {@literal null}.
|
||||
*/
|
||||
public PersistentEntityParameterValueProvider(PersistentEntity<?, P> entity, PropertyValueProvider<P> provider,
|
||||
Optional<Object> parent) {
|
||||
Object parent) {
|
||||
|
||||
Assert.notNull(entity, "Entity must not be null!");
|
||||
Assert.notNull(provider, "Provider must not be null!");
|
||||
Assert.notNull(parent, "Parent must not be null!");
|
||||
|
||||
this.entity = entity;
|
||||
this.provider = provider;
|
||||
@@ -64,18 +60,21 @@ public class PersistentEntityParameterValueProvider<P extends PersistentProperty
|
||||
* @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Optional<T> getParameterValue(Parameter<T, P> parameter) {
|
||||
public <T> T getParameterValue(Parameter<T, P> parameter) {
|
||||
|
||||
PreferredConstructor<?, P> constructor = entity.getPersistenceConstructor().get();
|
||||
PreferredConstructor<?, P> constructor = entity.getPersistenceConstructor().orElse(null);
|
||||
|
||||
if (constructor.isEnclosingClassParameter(parameter)) {
|
||||
return (Optional<T>) parent;
|
||||
return (T) parent;
|
||||
}
|
||||
|
||||
return provider.getPropertyValue(parameter.getName()//
|
||||
.flatMap(entity::getPersistentProperty)//
|
||||
.orElseThrow(() -> new MappingException(
|
||||
String.format("No property %s found on entity %s to bind constructor parameter to!", parameter.getName(),
|
||||
entity.getType()))));
|
||||
P property = entity.getPersistentProperty(parameter.getName().orElse(null)).orElse(null);
|
||||
|
||||
if (property == null) {
|
||||
throw new MappingException(String.format("No property %s found on entity %s to bind constructor parameter to!",
|
||||
parameter.getName(), entity.getType()));
|
||||
}
|
||||
|
||||
return provider.getPropertyValue(property);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,31 +28,40 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value object to abstract the concept of a property backed by a {@link Field} and / or a {@link PropertyDescriptor}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class Property {
|
||||
|
||||
private final @Getter Optional<Field> field;
|
||||
private final Optional<PropertyDescriptor> descriptor;
|
||||
|
||||
private final Lazy<Class<?>> rawType;
|
||||
private final Class<?> rawType;
|
||||
private final Lazy<Integer> hashCode;
|
||||
private final Optional<Method> getter;
|
||||
private final Optional<Method> setter;
|
||||
|
||||
private Property(Optional<Field> field, Optional<PropertyDescriptor> descriptor) {
|
||||
|
||||
this.field = field;
|
||||
this.descriptor = descriptor;
|
||||
this.hashCode = Lazy.of(this::computeHashCode);
|
||||
this.rawType = Lazy.of(
|
||||
() -> field.<Class<?>> map(Field::getType).orElseGet(() -> descriptor.map(PropertyDescriptor::getPropertyType)//
|
||||
.orElseThrow(IllegalStateException::new)));
|
||||
this.rawType = field.<Class<?>> map(Field::getType)
|
||||
.orElseGet(() -> descriptor.map(PropertyDescriptor::getPropertyType)//
|
||||
.orElse(null));
|
||||
|
||||
this.getter = descriptor.map(PropertyDescriptor::getReadMethod)//
|
||||
.filter(it -> getType() != null).filter(it -> getType().isAssignableFrom(it.getReturnType()));
|
||||
|
||||
this.setter = descriptor.map(PropertyDescriptor::getWriteMethod)//
|
||||
.filter(it -> getType() != null).filter(it -> it.getParameterTypes()[0].isAssignableFrom(getType()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Property} backed by the given field.
|
||||
*
|
||||
*
|
||||
* @param field must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -65,7 +74,7 @@ public class Property {
|
||||
|
||||
/**
|
||||
* Creates a new {@link Property} backed by the given {@link Field} and {@link PropertyDescriptor}.
|
||||
*
|
||||
*
|
||||
* @param field must not be {@literal null}.
|
||||
* @param descriptor must not be {@literal null}.
|
||||
* @return
|
||||
@@ -80,7 +89,7 @@ public class Property {
|
||||
|
||||
/**
|
||||
* Creates a new {@link Property} for the given {@link PropertyDescriptor}.
|
||||
*
|
||||
*
|
||||
* @param descriptor must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -93,7 +102,7 @@ public class Property {
|
||||
|
||||
/**
|
||||
* Returns whether the property is backed by a field.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isFieldBacked() {
|
||||
@@ -102,27 +111,25 @@ public class Property {
|
||||
|
||||
/**
|
||||
* Returns the getter of the property if available and if it matches the type of the property.
|
||||
*
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public Optional<Method> getGetter() {
|
||||
return descriptor.map(PropertyDescriptor::getReadMethod)//
|
||||
.filter(it -> getType().isAssignableFrom(it.getReturnType()));
|
||||
return getter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setter of the property if available and if its first (only) parameter matches the type of the property.
|
||||
*
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public Optional<Method> getSetter() {
|
||||
return descriptor.map(PropertyDescriptor::getWriteMethod)//
|
||||
.filter(it -> it.getParameterTypes()[0].isAssignableFrom(getType()));
|
||||
return setter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the property exposes a getter or a setter.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean hasAccessor() {
|
||||
@@ -131,7 +138,7 @@ public class Property {
|
||||
|
||||
/**
|
||||
* Returns the name of the property.
|
||||
*
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public String getName() {
|
||||
@@ -143,11 +150,11 @@ public class Property {
|
||||
|
||||
/**
|
||||
* Returns the type of the property.
|
||||
*
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public Class<?> getType() {
|
||||
return rawType.get();
|
||||
return rawType;
|
||||
}
|
||||
|
||||
private int computeHashCode() {
|
||||
@@ -156,7 +163,7 @@ public class Property {
|
||||
.orElseGet(() -> this.descriptor.map(PropertyDescriptor::hashCode).orElseThrow(IllegalStateException::new));
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@@ -165,7 +172,7 @@ public class Property {
|
||||
return hashCode.get();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@@ -185,7 +192,7 @@ public class Property {
|
||||
return this.field.isPresent() ? this.field.equals(that.field) : this.descriptor.equals(that.descriptor);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -15,22 +15,20 @@
|
||||
*/
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
|
||||
/**
|
||||
* SPI for components to provide values for as {@link PersistentProperty}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface PropertyValueProvider<P extends PersistentProperty<P>> {
|
||||
|
||||
/**
|
||||
* Returns a value for the given {@link PersistentProperty}.
|
||||
*
|
||||
*
|
||||
* @param property will never be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
<T> Optional<T> getPropertyValue(P property);
|
||||
<T> T getPropertyValue(P property);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PreferredConstructor.Parameter;
|
||||
@@ -25,8 +23,9 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* {@link ParameterValueProvider} that can be used to front a {@link ParameterValueProvider} delegate to prefer a Spel
|
||||
* expression evaluation over directly resolving the parameter value with the delegate.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class SpELExpressionParameterValueProvider<P extends PersistentProperty<P>>
|
||||
implements ParameterValueProvider<P> {
|
||||
@@ -39,7 +38,7 @@ public class SpELExpressionParameterValueProvider<P extends PersistentProperty<P
|
||||
* Creates a new {@link SpELExpressionParameterValueProvider} using the given {@link SpELExpressionEvaluator},
|
||||
* {@link ConversionService} and {@link ParameterValueProvider} delegate to forward calls to, that resolve parameters
|
||||
* that do not have a Spel expression configured with them.
|
||||
*
|
||||
*
|
||||
* @param evaluator must not be {@literal null}.
|
||||
* @param conversionService must not be {@literal null}.
|
||||
* @param delegate must not be {@literal null}.
|
||||
@@ -56,22 +55,24 @@ public class SpELExpressionParameterValueProvider<P extends PersistentProperty<P
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter)
|
||||
*/
|
||||
public <T> Optional<T> getParameterValue(Parameter<T, P> parameter) {
|
||||
public <T> T getParameterValue(Parameter<T, P> parameter) {
|
||||
|
||||
return parameter.getSpelExpression()//
|
||||
.map(it -> Optional.ofNullable(evaluator.evaluate(it))//
|
||||
.map(result -> potentiallyConvertSpelValue(result, parameter)))
|
||||
.orElseGet(() -> delegate.getParameterValue(parameter));
|
||||
if (!parameter.hasSpelExpression()) {
|
||||
return delegate == null ? null : delegate.getParameterValue(parameter);
|
||||
}
|
||||
|
||||
Object object = evaluator.evaluate(parameter.getSpelExpression().orElse(null));
|
||||
return object == null ? null : potentiallyConvertSpelValue(object, parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to allow to massage the value resulting from the Spel expression evaluation. Default implementation will
|
||||
* leverage the configured {@link ConversionService} to massage the value into the parameter type.
|
||||
*
|
||||
*
|
||||
* @param object the value to massage, will never be {@literal null}.
|
||||
* @param parameter the {@link Parameter} we create the value for
|
||||
* @return
|
||||
|
||||
Reference in New Issue
Block a user