Remove deprecations in PersistentPropertyAccessor.

Related issue: #2813.
This commit is contained in:
Oliver Drotbohm
2023-03-01 22:21:07 +01:00
parent 35a2f45736
commit 55e14952c8
4 changed files with 1 additions and 406 deletions

View File

@@ -17,7 +17,6 @@ package org.springframework.data.mapping;
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Domain service to allow accessing and setting {@link PersistentProperty}s of an entity. Usually obtained through
@@ -46,63 +45,6 @@ public interface PersistentPropertyAccessor<T> {
*/
void setProperty(PersistentProperty<?> property, @Nullable Object value);
/**
* Sets the given value for the {@link PersistentProperty} pointed to by the given {@link PersistentPropertyPath}. The
* lookup of intermediate values must not yield {@literal null}.
*
* @param path must not be {@literal null} or empty.
* @param value can be {@literal null}.
* @since 2.1
* @deprecated since 2.3, use {@link PersistentPropertyPathAccessor#setProperty(PersistentPropertyPath, Object)}
* instead.
*/
@Deprecated
default void setProperty(PersistentPropertyPath<? extends PersistentProperty<?>> path, @Nullable Object value) {
Assert.notNull(path, "PersistentPropertyPath must not be null");
Assert.isTrue(!path.isEmpty(), "PersistentPropertyPath must not be empty");
PersistentProperty<? extends PersistentProperty<?>> leafProperty = path.getLeafProperty();
PersistentPropertyPath<? extends PersistentProperty<?>> parentPath = path.getParentPath();
if (parentPath != null) {
PersistentProperty<? extends PersistentProperty<?>> parentProperty = parentPath.getLeafProperty();
if (parentProperty.isCollectionLike() || parentProperty.isMap()) {
throw new MappingException(
"Cannot traverse collection or map intermediate %s".formatted(parentPath.toDotPath()));
}
}
Object parent = parentPath == null ? getBean() : getProperty(parentPath);
if (parent == null) {
String nullIntermediateMessage = "Cannot lookup property %s on null intermediate; Original path was: %s on %s";
throw new MappingException(
String.format(nullIntermediateMessage, path.getParentPath(), path.toDotPath(),
getBean().getClass().getName()));
}
PersistentPropertyAccessor<?> accessor = parent == getBean() //
? this //
: leafProperty.getOwner().getPropertyAccessor(parent);
accessor.setProperty(leafProperty, value);
if (parentPath == null) {
return;
}
Object bean = accessor.getBean();
if (bean != parent) {
setProperty(parentPath, bean);
}
}
/**
* Returns the value of the given {@link PersistentProperty} of the underlying bean instance.
*
@@ -112,65 +54,6 @@ public interface PersistentPropertyAccessor<T> {
@Nullable
Object getProperty(PersistentProperty<?> property);
/**
* Return the value pointed to by the given {@link PersistentPropertyPath}. If the given path is empty, the wrapped
* bean is returned.
*
* @param path must not be {@literal null}.
* @return
* @since 2.1
* @deprecated since 2.3, use {@link PersistentPropertyPathAccessor#getProperty(PersistentPropertyPath)} instead
*/
@Deprecated
@Nullable
default Object getProperty(PersistentPropertyPath<? extends PersistentProperty<?>> path) {
return getProperty(path, new TraversalContext());
}
/**
* Return the value pointed to by the given {@link PersistentPropertyPath}. If the given path is empty, the wrapped
* bean is returned. On each path segment value lookup, the resulting value is post-processed by handlers registered
* on the given {@link TraversalContext} context. This can be used to unwrap container types that are encountered
* during the traversal.
*
* @param path must not be {@literal null}.
* @param context must not be {@literal null}.
* @return
* @since 2.2
* @deprecated since 2.3, use
* {@link PersistentPropertyPathAccessor#getProperty(PersistentPropertyPath, org.springframework.data.mapping.AccessOptions.GetOptions)}
* instead.
*/
@Nullable
@Deprecated
default Object getProperty(PersistentPropertyPath<? extends PersistentProperty<?>> path, TraversalContext context) {
Object bean = getBean();
Object current = bean;
if (path.isEmpty()) {
return bean;
}
for (PersistentProperty<?> property : path) {
if (current == null) {
String nullIntermediateMessage = "Cannot lookup property %s on null intermediate; Original path was: %s on %s";
throw new MappingException(
String.format(nullIntermediateMessage, property, path.toDotPath(), bean.getClass().getName()));
}
PersistentEntity<?, ? extends PersistentProperty<?>> entity = property.getOwner();
PersistentPropertyAccessor<Object> accessor = entity.getPropertyAccessor(current);
current = context.postProcess(property, accessor.getProperty(property));
}
return current;
}
/**
* Returns the underlying bean. The actual instance may change between
* {@link #setProperty(PersistentProperty, Object)} calls.

View File

@@ -37,10 +37,7 @@ public interface PersistentPropertyPathAccessor<T> extends PersistentPropertyAcc
* @return
*/
@Nullable
@SuppressWarnings("deprecation")
default Object getProperty(PersistentPropertyPath<? extends PersistentProperty<?>> path) {
return PersistentPropertyAccessor.super.getProperty(path);
}
Object getProperty(PersistentPropertyPath<? extends PersistentProperty<?>> path);
/**
* Return the value pointed to by the given {@link PersistentPropertyPath}. If the given path is empty, the wrapped

View File

@@ -1,146 +0,0 @@
/*
* Copyright 2019-2023 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
*
* https://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 java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* A context object for lookups of values for {@link PersistentPropertyPaths} via a {@link PersistentPropertyAccessor}.
* It allows to register functions to post-process the objects returned for a particular property, so that the
* subsequent traversal would rather use the processed object. This is especially helpful if you need to traverse paths
* that contain {@link Collection}s and {@link Map} that usually need indices and keys to reasonably traverse nested
* properties.
*
* @author Oliver Drotbohm
* @since 2.2
* @soundtrack 8-Bit Misfits - Crash Into Me (Dave Matthews Band cover)
*/
public class TraversalContext {
private Map<PersistentProperty<?>, Function<Object, Object>> handlers = new HashMap<>();
/**
* Registers a {@link Function} to post-process values for the given property.
*
* @param property must not be {@literal null}.
* @param handler must not be {@literal null}.
* @return
*/
public TraversalContext registerHandler(PersistentProperty<?> property, Function<Object, Object> handler) {
Assert.notNull(property, "Property must not be null");
Assert.notNull(handler, "Handler must not be null");
handlers.put(property, handler);
return this;
}
/**
* Registers a {@link Function} to handle {@link Collection} values for the given property.
*
* @param property must not be {@literal null}.
* @param handler must not be {@literal null}.
* @return
*/
@SuppressWarnings("unchecked")
public TraversalContext registerCollectionHandler(PersistentProperty<?> property,
Function<? super Collection<?>, Object> handler) {
return registerHandler(property, Collection.class, (Function<Object, Object>) handler);
}
/**
* Registers a {@link Function} to handle {@link List} values for the given property.
*
* @param property must not be {@literal null}.
* @param handler must not be {@literal null}.
* @return
*/
@SuppressWarnings("unchecked")
public TraversalContext registerListHandler(PersistentProperty<?> property,
Function<? super List<?>, Object> handler) {
return registerHandler(property, List.class, (Function<Object, Object>) handler);
}
/**
* Registers a {@link Function} to handle {@link Set} values for the given property.
*
* @param property must not be {@literal null}.
* @param handler must not be {@literal null}.
* @return
*/
@SuppressWarnings("unchecked")
public TraversalContext registerSetHandler(PersistentProperty<?> property, Function<? super Set<?>, Object> handler) {
return registerHandler(property, Set.class, (Function<Object, Object>) handler);
}
/**
* Registers a {@link Function} to handle {@link Map} values for the given property.
*
* @param property must not be {@literal null}.
* @param handler must not be {@literal null}.
* @return
*/
@SuppressWarnings("unchecked")
public TraversalContext registerMapHandler(PersistentProperty<?> property,
Function<? super Map<?, ?>, Object> handler) {
return registerHandler(property, Map.class, (Function<Object, Object>) handler);
}
/**
* Registers the given {@link Function} to post-process values obtained for the given {@link PersistentProperty} for
* the given type.
*
* @param <T> the type of the value to handle.
* @param property must not be {@literal null}.
* @param type must not be {@literal null}.
* @param handler must not be {@literal null}.
* @return
*/
public <T> TraversalContext registerHandler(PersistentProperty<?> property, Class<T> type,
Function<? super T, Object> handler) {
Assert.isTrue(type.isAssignableFrom(property.getType()), () -> String
.format("Cannot register a property handler for %s on a property of type %s", type, property.getType()));
Function<Object, T> caster = (Function<Object, T>) it -> type.cast(it);
return registerHandler(property, caster.andThen(handler));
}
/**
* Post-processes the value obtained for the given {@link PersistentProperty} using the registered handler.
*
* @param property must not be {@literal null}.
* @param value can be {@literal null}.
* @return the post-processed value or the value itself if no handlers registered.
*/
@Nullable
Object postProcess(PersistentProperty<?> property, @Nullable Object value) {
Function<Object, Object> handler = handlers.get(property);
return handler == null ? value : handler.apply(value);
}
}