You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by ah...@apache.org on 2024/11/12 04:38:55 UTC
(causeway) branch v3 updated: CAUSEWAY-2297: move attribute enum to class cache
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch v3
in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/v3 by this push:
new d09ede6c23e CAUSEWAY-2297: move attribute enum to class cache
d09ede6c23e is described below
commit d09ede6c23e2cd121b79e95b1ef4374a8ca6a366
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Nov 12 05:38:51 2024 +0100
CAUSEWAY-2297: move attribute enum to class cache
---
.../commons/internal/reflection/_ClassCache.java | 75 ++++++++++++----------
.../config/beans/CausewayBeanTypeClassifier.java | 72 +++++++--------------
.../config/beans/CausewayComponentCollector.java | 4 +-
.../RemoveAnnotatedMethodsFacetFactory.java | 5 +-
.../specimpl/dflt/ObjectSpecificationDefault.java | 6 +-
5 files changed, 69 insertions(+), 93 deletions(-)
diff --git a/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_ClassCache.java b/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_ClassCache.java
index 931bdd25dbf..acf7a702014 100644
--- a/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_ClassCache.java
+++ b/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_ClassCache.java
@@ -18,6 +18,7 @@
*/
package org.apache.causeway.commons.internal.reflection;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -37,6 +38,7 @@ import jakarta.xml.bind.annotation.XmlRootElement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.lang.Nullable;
@@ -80,6 +82,17 @@ import lombok.SneakyThrows;
*/
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public final class _ClassCache implements AutoCloseable {
+
+ public enum Attribute {
+ /**
+ * Corresponds to the bean name of Spring managed beans.
+ */
+ SPRING_NAMED,
+ /**
+ * Corresponds to DomainObject#mixinMethod().
+ */
+ MIXIN_MAIN_METHOD_NAME;
+ }
public static _ClassCache getInstance() {
return _Context.computeIfAbsent(_ClassCache.class, ()->new _ClassCache(_Context.getDefaultClassLoader()));
@@ -107,14 +120,14 @@ public final class _ClassCache implements AutoCloseable {
return classModel(type).head().named()!=null;
}
- public void setNamed(Class<?> beanClass, String beanDefinitionName) {
+ public void setSpringNamed(Class<?> beanClass, String beanDefinitionName) {
_Assert.assertNotEmpty(beanDefinitionName);
- classModel(beanClass).attributeMap().put("NAMED", beanDefinitionName);
+ classModel(beanClass).head().attributeMap().put(Attribute.SPRING_NAMED, beanDefinitionName);
}
public String getLogicalName(final Class<?> type) {
var model = classModel(type);
- return Optional.ofNullable(model.attributeMap().get("NAMED"))
+ return Optional.ofNullable(model.head().attributeMap().get(Attribute.SPRING_NAMED))
.or(()->Optional.ofNullable(model.head().named()))
.or(()->Optional.ofNullable(type.getCanonicalName()))
.orElseGet(type::getName);
@@ -244,49 +257,47 @@ public final class _ClassCache implements AutoCloseable {
}
}
- // -- ATTRIBUTES
-
- public _ClassCache setAttribute(
- final Class<?> type,
- final String attributeName,
- final String value) {
- var classModel = classModel(type);
- classModel.attributeMap.put(attributeName, value);
- return this;
- }
-
- public Optional<String> lookupAttribute(
- final Class<?> type,
- final String attributeName) {
- var classModel = classModel(type);
- return Optional.ofNullable(classModel.attributeMap.get(attributeName));
- }
-
// -- IMPLEMENATION DETAILS
public record ClassModelHead(
MergedAnnotations mergedAnnotations,
/** explicit name if any */
- @Nullable String named) {
+ @Nullable String named,
+ Map<Attribute, String> attributeMap) {
static ClassModelHead create(final Class<?> type) {
var mergedAnnotations = MergedAnnotations.from(type, SearchStrategy.TYPE_HIERARCHY);
- return new ClassModelHead(mergedAnnotations, _ClassCacheUtil.inferName(type, mergedAnnotations));
+ return new ClassModelHead(mergedAnnotations, _ClassCacheUtil.inferName(type, mergedAnnotations),
+ new ConcurrentHashMap<>());
+ }
+
+ /**
+ * @see MergedAnnotations#get(Class)
+ */
+ public <A extends Annotation> MergedAnnotation<A> annotation(Class<A> annotationType) {
+ return mergedAnnotations.get(annotationType);
+ }
+
+ /**
+ * whether type is annotated with annotationType
+ */
+ public boolean hasAnnotation(Class<? extends Annotation> annotationType) {
+ return mergedAnnotations.get(annotationType).isPresent();
}
/**
* whether type is annotated with {@link BeanInternal} or {@link Configuration}
*/
public boolean hasInternalBeanSemantics() {
- return mergedAnnotations.get(BeanInternal.class).isPresent()
- || mergedAnnotations.get(Configuration.class).isPresent();
+ return hasAnnotation(BeanInternal.class)
+ || hasAnnotation(Configuration.class);
}
/**
* whether type is annotated with {@link XmlRootElement}
*/
public boolean hasJaxbRootElementSemantics() {
- return mergedAnnotations.get(XmlRootElement.class).isPresent();
+ return hasAnnotation(XmlRootElement.class);
}
/**
@@ -308,10 +319,8 @@ public final class _ClassCache implements AutoCloseable {
Map<MethodKey, ResolvedMethod> resolvedMethodsByKey,
Map<MethodKey, ResolvedMethod> publicMethodsByKey,
Map<MethodKey, ResolvedMethod> postConstructMethodsByKey,
-
- Map<String, Can<ResolvedMethod>> declaredMethodsByAttribute,
- Map<String, String> attributeMap
- ) {
+
+ Map<String, Can<ResolvedMethod>> declaredMethodsByAttribute) {
ClassModel(
ClassModelHead head,
@@ -319,16 +328,14 @@ public final class _ClassCache implements AutoCloseable {
this(head,
declaredFields,
new HashMap<>(), new HashMap<>(), new HashMap<>(),
- new HashMap<>(), new HashMap<>(), new HashMap<>(),
- new ConcurrentHashMap<>());
+ new HashMap<>(), new HashMap<>(), new HashMap<>());
}
public static ClassModel headOnly(ClassModelHead head) {
return new ClassModel(head,
Can.empty(),
Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(),
- Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(),
- Collections.emptyMap());
+ Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap());
}
}
diff --git a/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanTypeClassifier.java b/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanTypeClassifier.java
index 43deaa3b753..f00e44e578c 100644
--- a/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanTypeClassifier.java
+++ b/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayBeanTypeClassifier.java
@@ -20,7 +20,6 @@ package org.apache.causeway.core.config.beans;
import java.io.Serializable;
import java.lang.reflect.Modifier;
-import java.util.Optional;
import java.util.function.Supplier;
import jakarta.persistence.Entity;
@@ -50,27 +49,6 @@ public record CausewayBeanTypeClassifier(
@NonNull Can<String> activeProfiles,
@NonNull _ClassCache classCache) {
- public enum Attributes {
- /**
- * Corresponds to presence of a {@link DomainService} annotation.
- * @see _ClassCache#lookupAttribute(Class, String)
- */
- HAS_DOMAIN_SERVICE_SEMANTICS,
-
- /**
- * Corresponds to {@link DomainObject#mixinMethod()}.
- * @see _ClassCache#lookupAttribute(Class, String)
- */
- MIXIN_MAIN_METHOD_NAME;
-
- public void set(final _ClassCache classCache, final Class<?> type, final String attributeValue) {
- classCache.setAttribute(type, this.name(), attributeValue);
- }
- public Optional<String> lookup(final _ClassCache classCache, final Class<?> type) {
- return classCache.lookupAttribute(type, this.name());
- }
- }
-
// -- CONSTRUCTION
CausewayBeanTypeClassifier(final ApplicationContext applicationContext) {
@@ -133,43 +111,37 @@ public record CausewayBeanTypeClassifier(
return CausewayBeanMetaData.notManaged(discoveredBy, BeanSort.VETOED, named.get()); // reject
}
- // handle value types ...
-
- var aValue = _Annotations.synthesize(type, org.apache.causeway.applib.annotation.Value.class)
- .orElse(null);
- if(aValue!=null) {
- return CausewayBeanMetaData.notManaged(discoveredBy, BeanSort.VALUE, named.get());
+ //[CAUSEWAY-3585] when implements ViewModel, then don't consider alternatives, yield VIEW_MODEL
+ if(org.apache.causeway.applib.ViewModel.class.isAssignableFrom(type)) {
+ return CausewayBeanMetaData.causewayManaged(discoveredBy, BeanSort.VIEW_MODEL, named.get());
}
- // handle internal bean types ...
+ var typeHead = classCache().head(type);
- if(classCache.head(type).hasInternalBeanSemantics()) {
+ // value types
+ if(typeHead.hasAnnotation(org.apache.causeway.applib.annotation.Value.class)) {
+ return CausewayBeanMetaData.notManaged(discoveredBy, BeanSort.VALUE, named.get());
+ }
+
+ // internal bean types
+ if(typeHead.hasInternalBeanSemantics()) {
return CausewayBeanMetaData.springManaged(discoveredBy, BeanSort.MANAGED_BEAN_NOT_CONTRIBUTING, logicalType);
}
- // handle actual bean types ...
-
- var aDomainService = _Annotations.synthesize(type, DomainService.class);
- if(aDomainService.isPresent()) {
- Attributes.HAS_DOMAIN_SERVICE_SEMANTICS.set(classCache, type, "true");
+ // domain service
+ if(typeHead.hasAnnotation(DomainService.class)) {
return CausewayBeanMetaData.springManaged(discoveredBy, BeanSort.MANAGED_BEAN_CONTRIBUTING, logicalType);
}
- //[CAUSEWAY-3585] when implements ViewModel, then don't consider alternatives, yield VIEW_MODEL
- if(org.apache.causeway.applib.ViewModel.class.isAssignableFrom(type)) {
- return CausewayBeanMetaData.causewayManaged(discoveredBy, BeanSort.VIEW_MODEL, named.get());
- }
-
- // JDO entity support
- if(classCache.head(type).isJdoPersistenceCapable()){
+ // entity support
+ if(typeHead.isJdoPersistenceCapable()){
return CausewayBeanMetaData.entity(discoveredBy, PersistenceStack.JDO, named.get());
}
-
- var entityAnnotation = _Annotations.synthesize(type, Entity.class).orElse(null);
- if(entityAnnotation!=null) {
+ if(typeHead.hasAnnotation(Entity.class)) {
return CausewayBeanMetaData.entity(discoveredBy, PersistenceStack.JPA, named.get());
- }
-
+ }
+
+ // domain object
var aDomainObject = _Annotations.synthesize(type, DomainObject.class).orElse(null);
if(aDomainObject!=null) {
switch (aDomainObject.nature()) {
@@ -177,7 +149,7 @@ public record CausewayBeanTypeClassifier(
return CausewayBeanMetaData.unspecified(discoveredBy, BeanSort.MANAGED_BEAN_CONTRIBUTING, named.get());
case MIXIN:
// memoize mixin main name
- Attributes.MIXIN_MAIN_METHOD_NAME.set(classCache, type, aDomainObject.mixinMethod());
+ typeHead.attributeMap().put(_ClassCache.Attribute.MIXIN_MAIN_METHOD_NAME, aDomainObject.mixinMethod());
return CausewayBeanMetaData.causewayManaged(discoveredBy, BeanSort.MIXIN, named.get());
case ENTITY:
return CausewayBeanMetaData.entity(discoveredBy, PersistenceStack.UNSPECIFIED, named.get());
@@ -188,11 +160,11 @@ public record CausewayBeanTypeClassifier(
}
}
- if(_ClassCache.getInstance().head(type).hasJaxbRootElementSemantics()) {
+ if(typeHead.hasJaxbRootElementSemantics()) {
return CausewayBeanMetaData.causewayManaged(discoveredBy, BeanSort.VIEW_MODEL, named.get());
}
- if(_Annotations.isPresent(type, Component.class)) {
+ if(typeHead.hasAnnotation(Component.class)) {
return CausewayBeanMetaData.unspecified(discoveredBy, BeanSort.MANAGED_BEAN_NOT_CONTRIBUTING, logicalType);
}
diff --git a/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayComponentCollector.java b/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayComponentCollector.java
index fc9e14c5457..0ded0d72a3f 100644
--- a/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayComponentCollector.java
+++ b/core/config/src/main/java/org/apache/causeway/core/config/beans/CausewayComponentCollector.java
@@ -71,13 +71,13 @@ record CausewayComponentCollector(
case UNSPECIFIED -> {
if(isRenamed) {
//rename(beanDefinition, beanDefinitionName, typeMeta.logicalType().logicalName()); //TODO does not work yet
- _ClassCache.getInstance().setNamed(beanClass, beanDefinitionName);
+ _ClassCache.getInstance().setSpringNamed(beanClass, beanDefinitionName);
}
}
case SPRING -> {
if(isRenamed) {
// renaming not allowed, report back to class-cache
- _ClassCache.getInstance().setNamed(beanClass, beanDefinitionName);
+ _ClassCache.getInstance().setSpringNamed(beanClass, beanDefinitionName);
}
}
}
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/ignore/annotation/RemoveAnnotatedMethodsFacetFactory.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/ignore/annotation/RemoveAnnotatedMethodsFacetFactory.java
index ff512a37b87..2d8d9dab8e5 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/ignore/annotation/RemoveAnnotatedMethodsFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/ignore/annotation/RemoveAnnotatedMethodsFacetFactory.java
@@ -23,8 +23,8 @@ import java.util.function.Predicate;
import jakarta.inject.Inject;
import org.apache.causeway.commons.internal.functions._Predicates;
+import org.apache.causeway.commons.internal.reflection._ClassCache.Attribute;
import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod;
-import org.apache.causeway.core.config.beans.CausewayBeanTypeClassifier.Attributes;
import org.apache.causeway.core.config.progmodel.ProgrammingModelConstants;
import org.apache.causeway.core.metamodel.context.MetaModelContext;
import org.apache.causeway.core.metamodel.facetapi.FeatureType;
@@ -100,8 +100,7 @@ extends FacetFactoryAbstract {
}
// lookup attribute from class-cache as it should have been already processed by the BeanTypeClassifier
var cls = processClassContext.getCls();
- var mixinMainMethodName = Attributes.MIXIN_MAIN_METHOD_NAME.lookup(getClassCache(), cls)
- .orElse(null);
+ var mixinMainMethodName = getClassCache().head(cls).attributeMap().get(Attribute.MIXIN_MAIN_METHOD_NAME);
return method->method.name().equals(mixinMainMethodName);
}
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index 4f7a8f09b31..a3ba504ac6f 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -27,6 +27,7 @@ import java.util.stream.Stream;
import org.springframework.lang.Nullable;
import org.apache.causeway.applib.Identifier;
+import org.apache.causeway.applib.annotation.DomainService;
import org.apache.causeway.applib.annotation.Introspection.IntrospectionPolicy;
import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.commons.collections.ImmutableEnumSet;
@@ -41,7 +42,6 @@ import org.apache.causeway.commons.internal.reflection._GenericResolver.Resolved
import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade;
import org.apache.causeway.commons.internal.reflection._Reflect;
import org.apache.causeway.core.config.beans.CausewayBeanMetaData;
-import org.apache.causeway.core.config.beans.CausewayBeanTypeClassifier.Attributes;
import org.apache.causeway.core.metamodel.commons.ToString;
import org.apache.causeway.core.metamodel.context.MetaModelContext;
import org.apache.causeway.core.metamodel.facetapi.FacetHolder;
@@ -353,9 +353,7 @@ implements FacetHolder {
}
private _Lazy<Boolean> isDomainServiceLazy = _Lazy.threadSafe(()->
- Attributes.HAS_DOMAIN_SERVICE_SEMANTICS.lookup(_ClassCache.getInstance(), getCorrespondingClass())
- .map("true"::equals)
- .orElse(false));
+ _ClassCache.getInstance().head(getCorrespondingClass()).hasAnnotation(DomainService.class));
@Override
public boolean isDomainService() {