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 2023/02/11 07:48:22 UTC

[causeway] 01/01: CAUSEWAY-3014: refactors EnumValueSemanticsAbstract

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch 3014-enum_title_not_honored
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit ac4377199b138bf2a1882854397270aa693dffd6
Author: andi-huber <ah...@apache.org>
AuthorDate: Sat Feb 11 08:48:14 2023 +0100

    CAUSEWAY-3014: refactors EnumValueSemanticsAbstract
    
    - delegate title concerns to the MMTitleUtil
---
 .../_testing/MetaModelContext_forTesting.java      |  3 +-
 .../specloader/SpecificationLoaderDefault.java     |  2 +-
 .../valuesemantics/EnumValueSemanticsAbstract.java | 74 +++++++++-------------
 .../valuetypes/ValueSemanticsResolverDefault.java  |  4 ++
 .../java/demoapp/dom/_infra/samples/DemoEnum.java  | 11 ++--
 5 files changed, 42 insertions(+), 52 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/_testing/MetaModelContext_forTesting.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/_testing/MetaModelContext_forTesting.java
index 3d292eb612..fd0030bfcd 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/_testing/MetaModelContext_forTesting.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/_testing/MetaModelContext_forTesting.java
@@ -314,7 +314,8 @@ implements MetaModelContext {
     private ValueSemanticsResolver valueSemanticsResolver;
     private ValueSemanticsResolver getValueSemanticsResolver(){
         if(valueSemanticsResolver==null) {
-            valueSemanticsResolver = new ValueSemanticsResolverDefault(valueSemantics, getTranslationService());
+            valueSemanticsResolver = new ValueSemanticsResolverDefault(valueSemantics,
+                    getTranslationService(), this::getSpecificationLoader);
         }
         return valueSemanticsResolver;
     }
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java
index 2fb788992f..e40e3c6fde 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java
@@ -197,7 +197,7 @@ implements
         val instance = new SpecificationLoaderDefault(
                 programmingModel, causewayConfiguration, causewaySystemEnvironment,
                 serviceRegistry, causewayBeanTypeClassifier, causewayBeanTypeRegistry,
-                ()->new ValueSemanticsResolverDefault(List.of(), null),
+                ()->new ValueSemanticsResolverDefault(List.of(), null, null),
                 classSubstitutorRegistry);
 
         instance.metaModelContext = serviceRegistry.lookupServiceElseFail(MetaModelContext.class);
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/EnumValueSemanticsAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/EnumValueSemanticsAbstract.java
index c6e42afcaf..6b38e7071c 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/EnumValueSemanticsAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/EnumValueSemanticsAbstract.java
@@ -18,13 +18,14 @@
  */
 package org.apache.causeway.core.metamodel.valuesemantics;
 
-import java.lang.reflect.Method;
+import java.util.Optional;
 import java.util.function.UnaryOperator;
 import java.util.stream.Stream;
 
+import javax.inject.Provider;
+
 import org.apache.causeway.applib.annotation.Introspection.IntrospectionPolicy;
 import org.apache.causeway.applib.exceptions.recoverable.TextEntryParseException;
-import org.apache.causeway.applib.services.i18n.TranslatableString;
 import org.apache.causeway.applib.services.i18n.TranslationContext;
 import org.apache.causeway.applib.services.i18n.TranslationService;
 import org.apache.causeway.applib.util.Enums;
@@ -37,9 +38,10 @@ import org.apache.causeway.applib.value.semantics.ValueSemanticsProvider;
 import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
-import org.apache.causeway.core.config.progmodel.ProgrammingModelConstants.ObjectSupportMethod;
-import org.apache.causeway.core.metamodel.commons.CanonicalInvoker;
-import org.apache.causeway.core.metamodel.methods.MethodFinder;
+import org.apache.causeway.core.metamodel.object.ManagedObject;
+import org.apache.causeway.core.metamodel.object.MmTitleUtil;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
+import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
 import org.apache.causeway.schema.common.v2.EnumDto;
 import org.apache.causeway.schema.common.v2.ValueType;
 import org.apache.causeway.schema.common.v2.ValueWithTypeDto;
@@ -56,20 +58,30 @@ implements
     Renderer<T> {
 
     private final TranslationService translationService;
-    private final Method titleMethod;
+    private final Provider<SpecificationLoader> specificationLoaderProvider;
     @Getter(onMethod_ = {@Override}) private final Class<T> correspondingClass;
     @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) private final int maxLength;
 
+    @Getter(lazy=true)
+    private final ObjectSpecification enumSpec =
+            Optional.ofNullable(specificationLoaderProvider)
+            .map(provider->provider.get())
+            .flatMap(specLoader->specLoader.specForType(correspondingClass))
+            .orElse(null);
+
+
     @Override
     public ValueType getSchemaValueType() {
         return ValueType.ENUM;
     }
 
     public static <T extends Enum<T>> EnumValueSemanticsAbstract<T> create(
+            final Provider<SpecificationLoader> specificationLoaderProvider,
             final TranslationService translationService,
             final IntrospectionPolicy introspectionPolicy,
             final Class<T> correspondingClass) {
         return new EnumValueSemanticsAbstract<>(
+                specificationLoaderProvider,
                 translationService,
                 introspectionPolicy,
                 correspondingClass){};
@@ -78,6 +90,7 @@ implements
     // -- CONSTRUCTION
 
     protected EnumValueSemanticsAbstract(
+            final Provider<SpecificationLoader> specificationLoaderProvider,
             final TranslationService translationService,
             final IntrospectionPolicy introspectionPolicy,
             final Class<T> correspondingClass) {
@@ -86,21 +99,7 @@ implements
         this.translationService = translationService;
         this.correspondingClass = correspondingClass;
         this.maxLength = maxLengthFor(correspondingClass);
-
-        val supportMethodEnum = ObjectSupportMethod.TITLE;
-
-        titleMethod =
-
-        MethodFinder
-        .objectSupport(
-                correspondingClass,
-                supportMethodEnum.getMethodNames(),
-                introspectionPolicy)
-        .withReturnTypeAnyOf(supportMethodEnum.getReturnTypeCategory().getReturnTypes())
-        .streamMethodsMatchingSignature(MethodFinder.NO_ARG)
-        .findFirst()
-        .orElse(null);
-
+        this.specificationLoaderProvider = specificationLoaderProvider;
     }
 
     // -- DEFAULTS PROVIDER
@@ -150,31 +149,16 @@ implements
         return renderHtml(value, v->friendlyName(context, v));
     }
 
-    private String friendlyName(final Context context, final T object) {
-        if (titleMethod != null) {
-            // sadness: same as in TranslationFactory
-            val translationContext = TranslationContext.forMethod(titleMethod);
-
-            try {
-                final Object returnValue = CanonicalInvoker.invoke(titleMethod, object);
-                if(returnValue instanceof String) {
-                    return (String) returnValue;
-                }
-                if(returnValue instanceof TranslatableString) {
-                    final TranslatableString ts = (TranslatableString) returnValue;
-                    return ts.translate(translationService, translationContext);
-                }
-                return null;
-            } catch (final RuntimeException ex) {
-                // fall through
-            }
-        }
+    private String friendlyName(final Context context, final T objectAsEnum) {
+
+        val friendlyNameOfEnum = Optional.ofNullable(this.getEnumSpec())
+            .map(enumSpec->ManagedObject.value(enumSpec, objectAsEnum))
+            .map(MmTitleUtil::titleOf)
+            .orElseGet(()->Enums.getFriendlyNameOf(objectAsEnum.name()));
 
-        // simply translate the enum constant's name
-        val objectAsEnum = object;
-        val translationContext = TranslationContext.forEnum(objectAsEnum);
-        final String friendlyNameOfEnum = Enums.getFriendlyNameOf(objectAsEnum.name());
-        return translationService.translate(translationContext, friendlyNameOfEnum);
+        return Optional.ofNullable(translationService)
+                .map(ts->ts.translate(TranslationContext.forEnum(objectAsEnum), friendlyNameOfEnum))
+                .orElse(friendlyNameOfEnum);
     }
 
     // -- PARSER
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuetypes/ValueSemanticsResolverDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuetypes/ValueSemanticsResolverDefault.java
index eeca20ae8b..802fb6c9d4 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuetypes/ValueSemanticsResolverDefault.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuetypes/ValueSemanticsResolverDefault.java
@@ -24,6 +24,7 @@ import java.util.stream.Stream;
 
 import javax.inject.Inject;
 import javax.inject.Named;
+import javax.inject.Provider;
 
 import org.springframework.stereotype.Service;
 import org.springframework.util.ClassUtils;
@@ -39,6 +40,7 @@ import org.apache.causeway.commons.internal.base._Casts;
 import org.apache.causeway.commons.internal.base._NullSafe;
 import org.apache.causeway.commons.internal.collections._Maps;
 import org.apache.causeway.core.metamodel.CausewayModuleCoreMetamodel;
+import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
 import org.apache.causeway.core.metamodel.valuesemantics.EnumValueSemanticsAbstract;
 
 import lombok.NonNull;
@@ -54,6 +56,7 @@ implements ValueSemanticsResolver {
     // managed by Spring
     private final List<ValueSemanticsProvider<?>> valueSemanticsProviders;
     private final TranslationService translationService;
+    private final Provider<SpecificationLoader> specificationLoaderProvider;
 
     @Override
     public boolean hasValueSemantics(final Class<?> valueType) {
@@ -109,6 +112,7 @@ implements ValueSemanticsResolver {
         return enumSemantics.computeIfAbsent(enumType, t->
                 EnumValueSemanticsAbstract
                   .create(
+                          null, //specificationLoader.specForType(enumType).orElse(null),
                           translationService,
                           // in order to simplify matters, we just assume this for enums
                           IntrospectionPolicy.ENCAPSULATION_ENABLED,
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/_infra/samples/DemoEnum.java b/examples/demo/domain/src/main/java/demoapp/dom/_infra/samples/DemoEnum.java
index baaa47ddb2..2594500a15 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/_infra/samples/DemoEnum.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/_infra/samples/DemoEnum.java
@@ -18,8 +18,8 @@
  */
 package demoapp.dom._infra.samples;
 
-import org.apache.causeway.applib.annotation.Title;
-import org.apache.causeway.commons.internal.base._Strings;
+import org.apache.causeway.applib.annotation.ObjectSupport;
+import org.apache.causeway.applib.util.Enums;
 
 import lombok.RequiredArgsConstructor;
 
@@ -32,11 +32,12 @@ public enum DemoEnum {
 
     final String symbol;
 
-    @Title
-    public String getTitle() {
+    //@Title
+    @ObjectSupport
+    public String title() {
         return String.format("%s %s",
                 symbol,
-                _Strings.asNaturalName2.apply(name()));
+                Enums.getFriendlyNameOf(name()));
     }
 
 }