DATACMNS-867 - First draft.
This commit is contained in:
@@ -21,6 +21,7 @@ import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.data.annotation.CreatedBy;
|
||||
@@ -29,6 +30,7 @@ import org.springframework.data.annotation.LastModifiedBy;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.convert.Jsr310Converters;
|
||||
import org.springframework.data.convert.ThreeTenBackPortConverters;
|
||||
import org.springframework.data.util.Optionals;
|
||||
import org.springframework.data.util.ReflectionUtils;
|
||||
import org.springframework.data.util.ReflectionUtils.AnnotationFieldFilter;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -68,10 +70,10 @@ final class AnnotationAuditingMetadata {
|
||||
SUPPORTED_DATE_TYPES = Collections.unmodifiableList(types);
|
||||
}
|
||||
|
||||
private final Field createdByField;
|
||||
private final Field createdDateField;
|
||||
private final Field lastModifiedByField;
|
||||
private final Field lastModifiedDateField;
|
||||
private final Optional<Field> createdByField;
|
||||
private final Optional<Field> createdDateField;
|
||||
private final Optional<Field> lastModifiedByField;
|
||||
private final Optional<Field> lastModifiedDateField;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AnnotationAuditingMetadata} instance for the given type.
|
||||
@@ -82,10 +84,10 @@ final class AnnotationAuditingMetadata {
|
||||
|
||||
Assert.notNull(type, "Given type must not be null!");
|
||||
|
||||
this.createdByField = ReflectionUtils.findField(type, CREATED_BY_FILTER);
|
||||
this.createdDateField = ReflectionUtils.findField(type, CREATED_DATE_FILTER);
|
||||
this.lastModifiedByField = ReflectionUtils.findField(type, LAST_MODIFIED_BY_FILTER);
|
||||
this.lastModifiedDateField = ReflectionUtils.findField(type, LAST_MODIFIED_DATE_FILTER);
|
||||
this.createdByField = Optional.ofNullable(ReflectionUtils.findField(type, CREATED_BY_FILTER));
|
||||
this.createdDateField = Optional.ofNullable(ReflectionUtils.findField(type, CREATED_DATE_FILTER));
|
||||
this.lastModifiedByField = Optional.ofNullable(ReflectionUtils.findField(type, LAST_MODIFIED_BY_FILTER));
|
||||
this.lastModifiedDateField = Optional.ofNullable(ReflectionUtils.findField(type, LAST_MODIFIED_DATE_FILTER));
|
||||
|
||||
assertValidDateFieldType(createdDateField);
|
||||
assertValidDateFieldType(lastModifiedDateField);
|
||||
@@ -94,23 +96,26 @@ final class AnnotationAuditingMetadata {
|
||||
/**
|
||||
* Checks whether the given field has a type that is a supported date type.
|
||||
*
|
||||
* @param field can be {@literal null}.
|
||||
* @param field
|
||||
*/
|
||||
private void assertValidDateFieldType(Field field) {
|
||||
private void assertValidDateFieldType(Optional<Field> field) {
|
||||
|
||||
if (field == null || SUPPORTED_DATE_TYPES.contains(field.getType().getName())) {
|
||||
return;
|
||||
}
|
||||
field.ifPresent(it -> {
|
||||
|
||||
Class<?> type = field.getType();
|
||||
if (SUPPORTED_DATE_TYPES.contains(it.getType().getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Jsr310Converters.supports(type) || ThreeTenBackPortConverters.supports(type)) {
|
||||
return;
|
||||
}
|
||||
Class<?> type = it.getType();
|
||||
|
||||
throw new IllegalStateException(String.format(
|
||||
"Found created/modified date field with type %s but only %s as well as java.time types are supported!", type,
|
||||
SUPPORTED_DATE_TYPES));
|
||||
if (Jsr310Converters.supports(type) || ThreeTenBackPortConverters.supports(type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new IllegalStateException(String.format(
|
||||
"Found created/modified date field with type %s but only %s as well as java.time types are supported!", type,
|
||||
SUPPORTED_DATE_TYPES));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,52 +124,41 @@ final class AnnotationAuditingMetadata {
|
||||
* @param type the type to inspect, must not be {@literal null}.
|
||||
*/
|
||||
public static AnnotationAuditingMetadata getMetadata(Class<?> type) {
|
||||
|
||||
if (METADATA_CACHE.containsKey(type)) {
|
||||
return METADATA_CACHE.get(type);
|
||||
}
|
||||
|
||||
AnnotationAuditingMetadata metadata = new AnnotationAuditingMetadata(type);
|
||||
METADATA_CACHE.put(type, metadata);
|
||||
return metadata;
|
||||
return METADATA_CACHE.computeIfAbsent(type, it -> new AnnotationAuditingMetadata(it));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the {@link Class} represented in this instance is auditable or not.
|
||||
*/
|
||||
public boolean isAuditable() {
|
||||
if (createdByField == null && createdDateField == null && lastModifiedByField == null
|
||||
&& lastModifiedDateField == null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return Optionals.isAnyPresent(createdByField, createdDateField, lastModifiedByField, lastModifiedDateField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the field annotated by {@link CreatedBy}, or {@literal null}.
|
||||
* Return the field annotated by {@link CreatedBy}.
|
||||
*/
|
||||
public Field getCreatedByField() {
|
||||
public Optional<Field> getCreatedByField() {
|
||||
return createdByField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the field annotated by {@link CreatedDate}, or {@literal null}.
|
||||
* Return the field annotated by {@link CreatedDate}.
|
||||
*/
|
||||
public Field getCreatedDateField() {
|
||||
public Optional<Field> getCreatedDateField() {
|
||||
return createdDateField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the field annotated by {@link LastModifiedBy}, or {@literal null}.
|
||||
* Return the field annotated by {@link LastModifiedBy}.
|
||||
*/
|
||||
public Field getLastModifiedByField() {
|
||||
public Optional<Field> getLastModifiedByField() {
|
||||
return lastModifiedByField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the field annotated by {@link LastModifiedDate}, or {@literal null}.
|
||||
* Return the field annotated by {@link LastModifiedDate}.
|
||||
*/
|
||||
public Field getLastModifiedDateField() {
|
||||
public Optional<Field> getLastModifiedDateField() {
|
||||
return lastModifiedDateField;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.auditing;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Interface to abstract the ways setting the auditing information can be implemented.
|
||||
@@ -30,34 +31,34 @@ public interface AuditableBeanWrapper {
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
void setCreatedBy(Object value);
|
||||
Optional<? extends Object> setCreatedBy(Optional<? extends Object> value);
|
||||
|
||||
/**
|
||||
* Set the date the object was created.
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
void setCreatedDate(Calendar value);
|
||||
Optional<TemporalAccessor> setCreatedDate(Optional<TemporalAccessor> value);
|
||||
|
||||
/**
|
||||
* Set the last modifier of the object.
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
void setLastModifiedBy(Object value);
|
||||
Optional<? extends Object> setLastModifiedBy(Optional<? extends Object> value);
|
||||
|
||||
/**
|
||||
* Returns the date of the last modification date of the backing bean.
|
||||
*
|
||||
* @return the date of the last modification, can be {@literal null}.
|
||||
* @return the date of the last modification.
|
||||
* @since 1.10
|
||||
*/
|
||||
Calendar getLastModifiedDate();
|
||||
Optional<TemporalAccessor> getLastModifiedDate();
|
||||
|
||||
/**
|
||||
* Set the last modification date.
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
void setLastModifiedDate(Calendar value);
|
||||
Optional<TemporalAccessor> setLastModifiedDate(Optional<TemporalAccessor> value);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.auditing;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A factory to lookup {@link AuditableBeanWrapper}s.
|
||||
*
|
||||
@@ -24,11 +26,10 @@ package org.springframework.data.auditing;
|
||||
public interface AuditableBeanWrapperFactory {
|
||||
|
||||
/**
|
||||
* Returns the {@link AuditableBeanWrapper} for the given source obejct if it's eligible for auditing.
|
||||
* Returns the {@link AuditableBeanWrapper} for the given source object if it's eligible for auditing.
|
||||
*
|
||||
* @param source can be {@literal null}.
|
||||
* @return the {@link AuditableBeanWrapper} for the given source obejct if it's eligible for auditing or
|
||||
* {@literal null} otherwise.
|
||||
* @param source.
|
||||
* @return the {@link AuditableBeanWrapper} for the given source object if it's eligible for auditing.
|
||||
*/
|
||||
AuditableBeanWrapper getBeanWrapperFor(Object source);
|
||||
Optional<AuditableBeanWrapper> getBeanWrapperFor(Optional<? extends Object> source);
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.auditing;
|
||||
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.slf4j.Logger;
|
||||
@@ -43,7 +44,7 @@ public class AuditingHandler implements InitializingBean {
|
||||
private final DefaultAuditableBeanWrapperFactory factory;
|
||||
|
||||
private DateTimeProvider dateTimeProvider = CurrentDateTimeProvider.INSTANCE;
|
||||
private AuditorAware<?> auditorAware;
|
||||
private Optional<AuditorAware<?>> auditorAware;
|
||||
private boolean dateTimeForNow = true;
|
||||
private boolean modifyOnCreation = true;
|
||||
|
||||
@@ -56,7 +57,6 @@ public class AuditingHandler implements InitializingBean {
|
||||
* @deprecated use {@link AuditingHandler(PersistentEntities)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("unchecked")
|
||||
public AuditingHandler(
|
||||
MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> mappingContext) {
|
||||
this(new PersistentEntities(Arrays.asList(mappingContext)));
|
||||
@@ -72,7 +72,9 @@ public class AuditingHandler implements InitializingBean {
|
||||
public AuditingHandler(PersistentEntities entities) {
|
||||
|
||||
Assert.notNull(entities, "PersistentEntities must not be null!");
|
||||
|
||||
this.factory = new MappingAuditableBeanWrapperFactory(entities);
|
||||
this.auditorAware = Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,10 +82,10 @@ public class AuditingHandler implements InitializingBean {
|
||||
*
|
||||
* @param auditorAware must not be {@literal null}.
|
||||
*/
|
||||
public void setAuditorAware(final AuditorAware<?> auditorAware) {
|
||||
public void setAuditorAware(AuditorAware<?> auditorAware) {
|
||||
|
||||
Assert.notNull(auditorAware, "AuditorAware must not be null!");
|
||||
this.auditorAware = auditorAware;
|
||||
this.auditorAware = Optional.of(auditorAware);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,7 +123,7 @@ public class AuditingHandler implements InitializingBean {
|
||||
*
|
||||
* @param source
|
||||
*/
|
||||
public void markCreated(Object source) {
|
||||
public void markCreated(Optional<? extends Object> source) {
|
||||
touch(source, true);
|
||||
}
|
||||
|
||||
@@ -130,35 +132,35 @@ public class AuditingHandler implements InitializingBean {
|
||||
*
|
||||
* @param source
|
||||
*/
|
||||
public void markModified(Object source) {
|
||||
public void markModified(Optional<? extends Object> source) {
|
||||
touch(source, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given source is considered to be auditable in the first place
|
||||
*
|
||||
* @param source can be {@literal null}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
protected final boolean isAuditable(Object source) {
|
||||
return factory.getBeanWrapperFor(source) != null;
|
||||
protected final boolean isAuditable(Optional<Object> source) {
|
||||
return source.flatMap(o -> factory.getBeanWrapperFor(source)).isPresent();
|
||||
}
|
||||
|
||||
private void touch(Object target, boolean isNew) {
|
||||
private void touch(Optional<? extends Object> target, boolean isNew) {
|
||||
|
||||
AuditableBeanWrapper wrapper = factory.getBeanWrapperFor(target);
|
||||
Optional<AuditableBeanWrapper> wrapper = factory.getBeanWrapperFor(target);
|
||||
|
||||
if (wrapper == null) {
|
||||
return;
|
||||
}
|
||||
wrapper.ifPresent(it -> {
|
||||
|
||||
Object auditor = touchAuditor(wrapper, isNew);
|
||||
Calendar now = dateTimeForNow ? touchDate(wrapper, isNew) : null;
|
||||
Optional<Object> auditor = touchAuditor(it, isNew);
|
||||
Optional<TemporalAccessor> now = dateTimeForNow ? touchDate(it, isNew) : Optional.empty();
|
||||
|
||||
Object defaultedNow = now == null ? "not set" : now;
|
||||
Object defaultedAuditor = auditor == null ? "unknown" : auditor;
|
||||
Object defaultedNow = now.map(Object::toString).orElse("not set");
|
||||
Object defaultedAuditor = auditor.map(Object::toString).orElse("unknown");
|
||||
|
||||
LOGGER.debug("Touched {} - Last modification at {} by {}", new Object[] { target, defaultedNow, defaultedAuditor });
|
||||
LOGGER.debug("Touched {} - Last modification at {} by {}",
|
||||
new Object[] { target, defaultedNow, defaultedAuditor });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,23 +169,22 @@ public class AuditingHandler implements InitializingBean {
|
||||
* @param auditable
|
||||
* @return
|
||||
*/
|
||||
private Object touchAuditor(AuditableBeanWrapper wrapper, boolean isNew) {
|
||||
private Optional<Object> touchAuditor(AuditableBeanWrapper wrapper, boolean isNew) {
|
||||
|
||||
if (null == auditorAware) {
|
||||
return null;
|
||||
}
|
||||
return auditorAware.map(it -> {
|
||||
|
||||
Object auditor = auditorAware.getCurrentAuditor();
|
||||
Optional<?> auditor = it.getCurrentAuditor();
|
||||
|
||||
if (isNew) {
|
||||
wrapper.setCreatedBy(auditor);
|
||||
if (!modifyOnCreation) {
|
||||
return auditor;
|
||||
if (isNew) {
|
||||
wrapper.setCreatedBy(auditor);
|
||||
if (!modifyOnCreation) {
|
||||
return auditor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wrapper.setLastModifiedBy(auditor);
|
||||
return auditor;
|
||||
return wrapper.setLastModifiedBy(auditor);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,9 +193,9 @@ public class AuditingHandler implements InitializingBean {
|
||||
* @param wrapper
|
||||
* @return
|
||||
*/
|
||||
private Calendar touchDate(AuditableBeanWrapper wrapper, boolean isNew) {
|
||||
private Optional<TemporalAccessor> touchDate(AuditableBeanWrapper wrapper, boolean isNew) {
|
||||
|
||||
Calendar now = dateTimeProvider.getNow();
|
||||
Optional<TemporalAccessor> now = dateTimeProvider.getNow();
|
||||
|
||||
if (isNew) {
|
||||
wrapper.setCreatedDate(now);
|
||||
@@ -203,8 +204,7 @@ public class AuditingHandler implements InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
wrapper.setLastModifiedDate(now);
|
||||
return now;
|
||||
return wrapper.setLastModifiedDate(now);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.auditing;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@@ -35,7 +36,7 @@ public enum CurrentDateTimeProvider implements DateTimeProvider {
|
||||
* @see org.springframework.data.auditing.DateTimeProvider#getNow()
|
||||
*/
|
||||
@Override
|
||||
public Calendar getNow() {
|
||||
return new GregorianCalendar();
|
||||
public Optional<TemporalAccessor> getNow() {
|
||||
return Optional.of(ZonedDateTime.now());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.auditing;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* SPI to calculate the current time to be used when auditing.
|
||||
@@ -30,5 +31,5 @@ public interface DateTimeProvider {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Calendar getNow();
|
||||
Optional<TemporalAccessor> getNow();
|
||||
}
|
||||
|
||||
@@ -15,21 +15,24 @@
|
||||
*/
|
||||
package org.springframework.data.auditing;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDateTime;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.convert.JodaTimeConverters;
|
||||
import org.springframework.data.convert.Jsr310Converters;
|
||||
import org.springframework.data.convert.ThreeTenBackPortConverters;
|
||||
import org.springframework.data.domain.Auditable;
|
||||
import org.springframework.data.util.ReflectionUtils;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* A factory class to {@link AuditableBeanWrapper} instances.
|
||||
@@ -46,23 +49,22 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public AuditableBeanWrapper getBeanWrapperFor(Object source) {
|
||||
public Optional<AuditableBeanWrapper> getBeanWrapperFor(Optional<? extends Object> source) {
|
||||
|
||||
return source.map(it -> {
|
||||
|
||||
if (it instanceof Auditable) {
|
||||
return new AuditableInterfaceBeanWrapper((Auditable<Object, ?, TemporalAccessor>) it);
|
||||
}
|
||||
|
||||
AnnotationAuditingMetadata metadata = AnnotationAuditingMetadata.getMetadata(it.getClass());
|
||||
|
||||
if (metadata.isAuditable()) {
|
||||
return new ReflectionAuditingBeanWrapper(it);
|
||||
}
|
||||
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (source instanceof Auditable) {
|
||||
return new AuditableInterfaceBeanWrapper((Auditable<Object, ?>) source);
|
||||
}
|
||||
|
||||
AnnotationAuditingMetadata metadata = AnnotationAuditingMetadata.getMetadata(source.getClass());
|
||||
|
||||
if (metadata.isAuditable()) {
|
||||
return new ReflectionAuditingBeanWrapper(source);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,36 +72,53 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static class AuditableInterfaceBeanWrapper extends DateConvertingAuditableBeanWrapper {
|
||||
|
||||
private final Auditable<Object, ?> auditable;
|
||||
private final @NonNull Auditable<Object, ?, TemporalAccessor> auditable;
|
||||
private final Class<? extends TemporalAccessor> type;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public AuditableInterfaceBeanWrapper(Auditable<Object, ?, TemporalAccessor> auditable) {
|
||||
|
||||
public AuditableInterfaceBeanWrapper(Auditable<Object, ?> auditable) {
|
||||
this.auditable = auditable;
|
||||
this.type = (Class<? extends TemporalAccessor>) ResolvableType.forClass(Auditable.class, auditable.getClass())
|
||||
.getGeneric(2).getRawClass();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedBy(java.lang.Object)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedBy(java.util.Optional)
|
||||
*/
|
||||
public void setCreatedBy(Object value) {
|
||||
@Override
|
||||
public Optional<? extends Object> setCreatedBy(Optional<? extends Object> value) {
|
||||
|
||||
auditable.setCreatedBy(value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedDate(org.joda.time.DateTime)
|
||||
*/
|
||||
public void setCreatedDate(Calendar value) {
|
||||
auditable.setCreatedDate(new DateTime(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedBy(java.lang.Object)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedDate(java.util.Optional)
|
||||
*/
|
||||
public void setLastModifiedBy(Object value) {
|
||||
@Override
|
||||
public Optional<TemporalAccessor> setCreatedDate(Optional<TemporalAccessor> value) {
|
||||
|
||||
auditable.setCreatedDate(getAsTemporalAccessor(value, type));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.DefaultAuditableBeanWrapperFactory.AuditableInterfaceBeanWrapper#setLastModifiedBy(java.util.Optional)
|
||||
*/
|
||||
@Override
|
||||
public Optional<? extends Object> setLastModifiedBy(Optional<? extends Object> value) {
|
||||
auditable.setLastModifiedBy(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -107,16 +126,20 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#getLastModifiedDate()
|
||||
*/
|
||||
@Override
|
||||
public Calendar getLastModifiedDate() {
|
||||
return getAsCalendar(auditable.getLastModifiedDate());
|
||||
public Optional<TemporalAccessor> getLastModifiedDate() {
|
||||
return getAsTemporalAccessor(auditable.getLastModifiedDate(), TemporalAccessor.class);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedDate(org.joda.time.DateTime)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedDate(java.util.Optional)
|
||||
*/
|
||||
public void setLastModifiedDate(Calendar value) {
|
||||
auditable.setLastModifiedDate(new DateTime(value));
|
||||
@Override
|
||||
public Optional<TemporalAccessor> setLastModifiedDate(Optional<TemporalAccessor> value) {
|
||||
|
||||
auditable.setLastModifiedDate(getAsTemporalAccessor(value, type));
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,9 +152,6 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
|
||||
*/
|
||||
abstract static class DateConvertingAuditableBeanWrapper implements AuditableBeanWrapper {
|
||||
|
||||
private static final boolean IS_JODA_TIME_PRESENT = ClassUtils.isPresent("org.joda.time.DateTime",
|
||||
ReflectionAuditingBeanWrapper.class.getClassLoader());
|
||||
|
||||
private final ConversionService conversionService;
|
||||
|
||||
/**
|
||||
@@ -141,18 +161,9 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
|
||||
|
||||
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
|
||||
|
||||
if (IS_JODA_TIME_PRESENT) {
|
||||
conversionService.addConverter(CalendarToDateTimeConverter.INSTANCE);
|
||||
conversionService.addConverter(CalendarToLocalDateTimeConverter.INSTANCE);
|
||||
}
|
||||
|
||||
for (Converter<?, ?> converter : Jsr310Converters.getConvertersToRegister()) {
|
||||
conversionService.addConverter(converter);
|
||||
}
|
||||
|
||||
for (Converter<?, ?> converter : ThreeTenBackPortConverters.getConvertersToRegister()) {
|
||||
conversionService.addConverter(converter);
|
||||
}
|
||||
JodaTimeConverters.getConvertersToRegister().forEach(it -> conversionService.addConverter(it));
|
||||
Jsr310Converters.getConvertersToRegister().forEach(it -> conversionService.addConverter(it));
|
||||
ThreeTenBackPortConverters.getConvertersToRegister().forEach(it -> conversionService.addConverter(it));
|
||||
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
@@ -165,28 +176,27 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
|
||||
* @param source must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
protected Object getDateValueToSet(Calendar value, Class<?> targetType, Object source) {
|
||||
protected Optional<Object> getDateValueToSet(Optional<TemporalAccessor> value, Class<?> targetType, Object source) {
|
||||
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return value.map(it -> {
|
||||
|
||||
if (Calendar.class.equals(targetType)) {
|
||||
return value;
|
||||
}
|
||||
if (TemporalAccessor.class.equals(targetType)) {
|
||||
return it;
|
||||
}
|
||||
|
||||
if (conversionService.canConvert(Calendar.class, targetType)) {
|
||||
return conversionService.convert(value, targetType);
|
||||
}
|
||||
if (conversionService.canConvert(it.getClass(), targetType)) {
|
||||
return conversionService.convert(it, targetType);
|
||||
}
|
||||
|
||||
if (conversionService.canConvert(Date.class, targetType)) {
|
||||
if (conversionService.canConvert(Date.class, targetType)) {
|
||||
|
||||
Date date = conversionService.convert(value, Date.class);
|
||||
return conversionService.convert(date, targetType);
|
||||
}
|
||||
Date date = conversionService.convert(it, Date.class);
|
||||
return conversionService.convert(date, targetType);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Invalid date type for member %s! Supported types are %s.",
|
||||
source, AnnotationAuditingMetadata.SUPPORTED_DATE_TYPES));
|
||||
throw new IllegalArgumentException(String.format("Invalid date type for member %s! Supported types are %s.",
|
||||
source, AnnotationAuditingMetadata.SUPPORTED_DATE_TYPES));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,22 +205,17 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
|
||||
* @param source can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
protected Calendar getAsCalendar(Object source) {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> Optional<T> getAsTemporalAccessor(Optional<?> source, Class<T> target) {
|
||||
|
||||
if (source == null || source instanceof Calendar) {
|
||||
return (Calendar) source;
|
||||
}
|
||||
|
||||
// Apply conversion to date if necessary and possible
|
||||
source = !(source instanceof Date) && conversionService.canConvert(source.getClass(), Date.class) ? conversionService
|
||||
.convert(source, Date.class) : source;
|
||||
|
||||
return conversionService.convert(source, Calendar.class);
|
||||
return source.map(it -> {
|
||||
return target.isInstance(it) ? (T) it : conversionService.convert(it, target);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An {@link AuditableBeanWrapper} implementation that sets values on the target object using refelction.
|
||||
* An {@link AuditableBeanWrapper} implementation that sets values on the target object using reflection.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -234,26 +239,29 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedBy(java.lang.Object)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedBy(java.util.Optional)
|
||||
*/
|
||||
public void setCreatedBy(Object value) {
|
||||
setField(metadata.getCreatedByField(), value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedDate(java.util.Calendar)
|
||||
*/
|
||||
public void setCreatedDate(Calendar value) {
|
||||
setDateField(metadata.getCreatedDateField(), value);
|
||||
@Override
|
||||
public Optional<? extends Object> setCreatedBy(Optional<? extends Object> value) {
|
||||
return setField(metadata.getCreatedByField(), value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedBy(java.lang.Object)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedDate(java.util.Optional)
|
||||
*/
|
||||
public void setLastModifiedBy(Object value) {
|
||||
setField(metadata.getLastModifiedByField(), value);
|
||||
@Override
|
||||
public Optional<TemporalAccessor> setCreatedDate(Optional<TemporalAccessor> value) {
|
||||
return setDateField(metadata.getCreatedDateField(), value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedBy(java.util.Optional)
|
||||
*/
|
||||
@Override
|
||||
public Optional<? extends Object> setLastModifiedBy(Optional<? extends Object> value) {
|
||||
return setField(metadata.getLastModifiedByField(), value);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -261,18 +269,39 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#getLastModifiedDate()
|
||||
*/
|
||||
@Override
|
||||
public Calendar getLastModifiedDate() {
|
||||
public Optional<TemporalAccessor> getLastModifiedDate() {
|
||||
|
||||
return getAsCalendar(org.springframework.util.ReflectionUtils.getField(metadata.getLastModifiedDateField(),
|
||||
target));
|
||||
return getAsTemporalAccessor(metadata.getLastModifiedDateField().map(field -> {
|
||||
|
||||
Object value = org.springframework.util.ReflectionUtils.getField(field, target);
|
||||
return Optional.class.isInstance(value) ? ((Optional<?>) value).orElse(null) : value;
|
||||
|
||||
}), TemporalAccessor.class);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedDate(java.util.Calendar)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedDate(java.util.Optional)
|
||||
*/
|
||||
public void setLastModifiedDate(Calendar value) {
|
||||
setDateField(metadata.getLastModifiedDateField(), value);
|
||||
@Override
|
||||
public Optional<TemporalAccessor> setLastModifiedDate(Optional<TemporalAccessor> value) {
|
||||
return setDateField(metadata.getLastModifiedDateField(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given field to the given value if present.
|
||||
*
|
||||
* @param field
|
||||
* @param value
|
||||
*/
|
||||
private Optional<? extends Object> setField(Optional<Field> field, Optional<? extends Object> value) {
|
||||
|
||||
field.ifPresent(it -> {
|
||||
ReflectionUtils.setField(it, target,
|
||||
Optional.class.isAssignableFrom(it.getType()) ? value : value.orElse(null));
|
||||
});
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,46 +310,15 @@ class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory
|
||||
* @param field
|
||||
* @param value
|
||||
*/
|
||||
private void setField(Field field, Object value) {
|
||||
private Optional<TemporalAccessor> setDateField(Optional<Field> field, Optional<TemporalAccessor> value) {
|
||||
|
||||
if (field != null) {
|
||||
ReflectionUtils.setField(field, target, value);
|
||||
}
|
||||
}
|
||||
field.ifPresent(it -> {
|
||||
Optional<Object> toSet = getDateValueToSet(value, it.getType(), it);
|
||||
ReflectionUtils.setField(it, target,
|
||||
Optional.class.isAssignableFrom(it.getType()) ? toSet : toSet.orElse(null));
|
||||
});
|
||||
|
||||
/**
|
||||
* Sets the given field to the given value if the field is not {@literal null}.
|
||||
*
|
||||
* @param field
|
||||
* @param value
|
||||
*/
|
||||
private void setDateField(Field field, Calendar value) {
|
||||
|
||||
if (field == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReflectionUtils.setField(field, target, getDateValueToSet(value, field.getType(), field));
|
||||
}
|
||||
}
|
||||
|
||||
private static enum CalendarToDateTimeConverter implements Converter<Calendar, DateTime> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public DateTime convert(Calendar source) {
|
||||
return new DateTime(source);
|
||||
}
|
||||
}
|
||||
|
||||
private static enum CalendarToLocalDateTimeConverter implements Converter<Calendar, LocalDateTime> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public LocalDateTime convert(Calendar source) {
|
||||
return new LocalDateTime(source);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.auditing;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
@@ -24,11 +25,12 @@ import org.springframework.data.mapping.context.MappingContextIsNewStrategyFacto
|
||||
import org.springframework.data.mapping.context.PersistentEntities;
|
||||
import org.springframework.data.support.IsNewStrategy;
|
||||
import org.springframework.data.support.IsNewStrategyFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link AuditingHandler} extension that uses an {@link IsNewStrategyFactory} to expose a generic
|
||||
* {@link #markAudited(Object)} method that will route calls to {@link #markCreated(Object)} or
|
||||
* {@link #markModified(Object)} based on the {@link IsNewStrategy} determined from the factory.
|
||||
* {@link #markAudited(Optional)} method that will route calls to {@link #markCreated(Optional)} or
|
||||
* {@link #markModified(Optional)} based on the {@link IsNewStrategy} determined from the factory.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 1.5
|
||||
@@ -45,7 +47,6 @@ public class IsNewAwareAuditingHandler extends AuditingHandler {
|
||||
* @deprecated use {@link IsNewAwareAuditingHandler(PersistentEntities)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("unchecked")
|
||||
public IsNewAwareAuditingHandler(
|
||||
MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> mappingContext) {
|
||||
this(new PersistentEntities(Arrays.asList(mappingContext)));
|
||||
@@ -54,7 +55,7 @@ public class IsNewAwareAuditingHandler extends AuditingHandler {
|
||||
/**
|
||||
* Creates a new {@link IsNewAwareAuditingHandler} for the given {@link MappingContext}.
|
||||
*
|
||||
* @param mappingContext must not be {@literal null}.
|
||||
* @param entities must not be {@literal null}.
|
||||
* @since 1.10
|
||||
*/
|
||||
public IsNewAwareAuditingHandler(PersistentEntities entities) {
|
||||
@@ -66,23 +67,28 @@ public class IsNewAwareAuditingHandler extends AuditingHandler {
|
||||
|
||||
/**
|
||||
* Marks the given object created or modified based on the {@link IsNewStrategy} returned by the
|
||||
* {@link IsNewStrategyFactory} configured. Will rout the calls to {@link #markCreated(Object)} and
|
||||
* {@link #markModified(Object)} accordingly.
|
||||
* {@link IsNewStrategyFactory} configured. Will rout the calls to {@link #markCreated(Optional)} and
|
||||
* {@link #markModified(Optional)} accordingly.
|
||||
*
|
||||
* @param object
|
||||
*/
|
||||
public void markAudited(Object object) {
|
||||
public void markAudited(Optional<Object> object) {
|
||||
|
||||
Assert.notNull(object, "Source object must not be null!");
|
||||
|
||||
if (!isAuditable(object)) {
|
||||
return;
|
||||
}
|
||||
|
||||
IsNewStrategy strategy = isNewStrategyFactory.getIsNewStrategy(object.getClass());
|
||||
object.ifPresent(it -> {
|
||||
|
||||
if (strategy.isNew(object)) {
|
||||
markCreated(object);
|
||||
} else {
|
||||
markModified(object);
|
||||
}
|
||||
IsNewStrategy strategy = isNewStrategyFactory.getIsNewStrategy(it.getClass());
|
||||
|
||||
if (strategy.isNew(object)) {
|
||||
markCreated(object);
|
||||
} else {
|
||||
markModified(object);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.auditing;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.annotation.CreatedBy;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
@@ -29,6 +30,7 @@ import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.context.PersistentEntities;
|
||||
import org.springframework.data.util.Optionals;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -62,32 +64,27 @@ public class MappingAuditableBeanWrapperFactory extends DefaultAuditableBeanWrap
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapperFactory#getBeanWrapperFor(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public AuditableBeanWrapper getBeanWrapperFor(Object source) {
|
||||
public Optional<AuditableBeanWrapper> getBeanWrapperFor(Optional<? extends Object> source) {
|
||||
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
return source.flatMap(it -> {
|
||||
|
||||
if (source instanceof Auditable) {
|
||||
return super.getBeanWrapperFor(source);
|
||||
}
|
||||
if (it instanceof Auditable) {
|
||||
return super.getBeanWrapperFor(source);
|
||||
}
|
||||
|
||||
Class<?> type = source.getClass();
|
||||
PersistentEntity<?, ?> entity = entities.getPersistentEntity(type);
|
||||
Class<?> type = it.getClass();
|
||||
PersistentEntity<?, ?> entity = entities.getPersistentEntity(type);
|
||||
|
||||
if (entity == null) {
|
||||
return super.getBeanWrapperFor(source);
|
||||
}
|
||||
if (entity == null) {
|
||||
return super.getBeanWrapperFor(source);
|
||||
}
|
||||
|
||||
MappingAuditingMetadata metadata = metadataCache.get(type);
|
||||
MappingAuditingMetadata metadata = metadataCache.computeIfAbsent(type,
|
||||
foo -> new MappingAuditingMetadata(entity));
|
||||
|
||||
if (metadata == null) {
|
||||
metadata = new MappingAuditingMetadata(entity);
|
||||
metadataCache.put(type, metadata);
|
||||
}
|
||||
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(source);
|
||||
return metadata.isAuditable() ? new MappingMetadataAuditableBeanWrapper(accessor, metadata) : null;
|
||||
return Optional.ofNullable(metadata.isAuditable()
|
||||
? new MappingMetadataAuditableBeanWrapper(entity.getPropertyAccessor(it), metadata) : null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,8 +95,8 @@ public class MappingAuditableBeanWrapperFactory extends DefaultAuditableBeanWrap
|
||||
*/
|
||||
static class MappingAuditingMetadata {
|
||||
|
||||
private final PersistentProperty<?> createdByProperty, createdDateProperty, lastModifiedByProperty,
|
||||
lastModifiedDateProperty;
|
||||
private final Optional<? extends PersistentProperty<?>> createdByProperty, createdDateProperty,
|
||||
lastModifiedByProperty, lastModifiedDateProperty;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingAuditingMetadata} instance from the given {@link PersistentEntity}.
|
||||
@@ -123,8 +120,8 @@ public class MappingAuditableBeanWrapperFactory extends DefaultAuditableBeanWrap
|
||||
* @return
|
||||
*/
|
||||
public boolean isAuditable() {
|
||||
return createdByProperty != null || createdDateProperty != null || lastModifiedByProperty != null
|
||||
|| lastModifiedDateProperty != null;
|
||||
return Optionals.isAnyPresent(createdByProperty, createdDateProperty, lastModifiedByProperty,
|
||||
lastModifiedDateProperty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,40 +155,44 @@ public class MappingAuditableBeanWrapperFactory extends DefaultAuditableBeanWrap
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedBy(java.lang.Object)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedBy(java.util.Optional)
|
||||
*/
|
||||
@Override
|
||||
public void setCreatedBy(Object value) {
|
||||
public Optional<? extends Object> setCreatedBy(Optional<? extends Object> value) {
|
||||
|
||||
if (metadata.createdByProperty != null) {
|
||||
this.accessor.setProperty(metadata.createdByProperty, value);
|
||||
}
|
||||
metadata.createdByProperty.ifPresent(it -> {
|
||||
this.accessor.setProperty(it, value);
|
||||
});
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedDate(java.util.Calendar)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setCreatedDate(java.util.Optional)
|
||||
*/
|
||||
@Override
|
||||
public void setCreatedDate(Calendar value) {
|
||||
public Optional<TemporalAccessor> setCreatedDate(Optional<TemporalAccessor> value) {
|
||||
|
||||
PersistentProperty<?> property = metadata.createdDateProperty;
|
||||
metadata.createdDateProperty.ifPresent(it -> {
|
||||
this.accessor.setProperty(it, getDateValueToSet(value, it.getType(), it));
|
||||
});
|
||||
|
||||
if (property != null) {
|
||||
this.accessor.setProperty(property, getDateValueToSet(value, property.getType(), property));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedBy(java.lang.Object)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedBy(java.util.Optional)
|
||||
*/
|
||||
@Override
|
||||
public void setLastModifiedBy(Object value) {
|
||||
public Optional<? extends Object> setLastModifiedBy(Optional<? extends Object> value) {
|
||||
|
||||
if (metadata.lastModifiedByProperty != null) {
|
||||
this.accessor.setProperty(metadata.lastModifiedByProperty, value);
|
||||
}
|
||||
metadata.lastModifiedByProperty.ifPresent(it -> {
|
||||
this.accessor.setProperty(it, value);
|
||||
});
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -199,29 +200,23 @@ public class MappingAuditableBeanWrapperFactory extends DefaultAuditableBeanWrap
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#getLastModifiedDate()
|
||||
*/
|
||||
@Override
|
||||
public Calendar getLastModifiedDate() {
|
||||
|
||||
PersistentProperty<?> property = metadata.lastModifiedDateProperty;
|
||||
|
||||
if (property == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getAsCalendar(accessor.getProperty(property));
|
||||
public Optional<TemporalAccessor> getLastModifiedDate() {
|
||||
return getAsTemporalAccessor(metadata.lastModifiedDateProperty.map(it -> accessor.getProperty(it)),
|
||||
TemporalAccessor.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedDate(java.util.Calendar)
|
||||
* @see org.springframework.data.auditing.AuditableBeanWrapper#setLastModifiedDate(java.util.Optional)
|
||||
*/
|
||||
@Override
|
||||
public void setLastModifiedDate(Calendar value) {
|
||||
public Optional<TemporalAccessor> setLastModifiedDate(Optional<TemporalAccessor> value) {
|
||||
|
||||
PersistentProperty<?> property = metadata.lastModifiedDateProperty;
|
||||
metadata.lastModifiedDateProperty.ifPresent(it -> {
|
||||
this.accessor.setProperty(it, getDateValueToSet(value, it.getType(), it));
|
||||
});
|
||||
|
||||
if (property != null) {
|
||||
this.accessor.setProperty(property, getDateValueToSet(value, property.getType(), property));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user