org.springframework.data.auditing.AnnotationAuditingMetadata Maven / Gradle / Ivy
/*
* Copyright 2012-2024 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.auditing;
import java.lang.reflect.Field;
import java.util.ArrayList;
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;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.convert.Jsr310Converters;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.data.util.ReflectionUtils.AnnotationFieldFilter;
import org.springframework.util.Assert;
/**
* Inspects the given {@link Class} for fields annotated by {@link CreatedBy}, {@link CreatedDate},
* {@link LastModifiedBy} , and {@link LastModifiedDate}. Only one field per annotation is stored.
*
* @author Ranie Jade Ramiso
* @author Oliver Gierke
* @author Christoph Strobl
* @author Johannes Englmeier
* @since 1.5
*/
final class AnnotationAuditingMetadata {
private static final AnnotationFieldFilter CREATED_BY_FILTER = new AnnotationFieldFilter(CreatedBy.class);
private static final AnnotationFieldFilter CREATED_DATE_FILTER = new AnnotationFieldFilter(CreatedDate.class);
private static final AnnotationFieldFilter LAST_MODIFIED_BY_FILTER = new AnnotationFieldFilter(LastModifiedBy.class);
private static final AnnotationFieldFilter LAST_MODIFIED_DATE_FILTER = new AnnotationFieldFilter(
LastModifiedDate.class);
private static final Map, AnnotationAuditingMetadata> metadataCache = new ConcurrentHashMap<>();
static final List SUPPORTED_DATE_TYPES;
static {
List types = new ArrayList<>(3);
types.add(Date.class.getName());
types.add(Long.class.getName());
types.add(long.class.getName());
SUPPORTED_DATE_TYPES = Collections.unmodifiableList(types);
}
private final Optional createdByField;
private final Optional createdDateField;
private final Optional lastModifiedByField;
private final Optional lastModifiedDateField;
/**
* Creates a new {@link AnnotationAuditingMetadata} instance for the given type.
*
* @param type must not be {@literal null}.
*/
private AnnotationAuditingMetadata(Class> type) {
Assert.notNull(type, "Given type must not be null");
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);
}
/**
* Checks whether the given field has a type that is a supported date type.
*
* @param field
*/
private void assertValidDateFieldType(Optional field) {
field.ifPresent(it -> {
if (SUPPORTED_DATE_TYPES.contains(it.getType().getName())) {
return;
}
Class> type = it.getType();
if (Jsr310Converters.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));
});
}
/**
* Return a {@link AnnotationAuditingMetadata} for the given {@link Class}.
*
* @param type the type to inspect, must not be {@literal null}.
*/
public static AnnotationAuditingMetadata getMetadata(Class> type) {
return metadataCache.computeIfAbsent(type, AnnotationAuditingMetadata::new);
}
/**
* Returns whether the {@link Class} represented in this instance is auditable or not.
*/
public boolean isAuditable() {
return Optionals.isAnyPresent(createdByField, createdDateField, lastModifiedByField, lastModifiedDateField);
}
/**
* Return the field annotated by {@link CreatedBy}.
*/
public Optional getCreatedByField() {
return createdByField;
}
/**
* Return the field annotated by {@link CreatedDate}.
*/
public Optional getCreatedDateField() {
return createdDateField;
}
/**
* Return the field annotated by {@link LastModifiedBy}.
*/
public Optional getLastModifiedByField() {
return lastModifiedByField;
}
/**
* Return the field annotated by {@link LastModifiedDate}.
*/
public Optional getLastModifiedDateField() {
return lastModifiedDateField;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy