You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2020/01/09 18:25:39 UTC

[isis] branch master updated (76d8846 -> 6865b1a)

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

danhaywood pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git.


    from 76d8846  ISIS-2158: further decouple from resteasy
     new 4ae7a3d  ISIS-2250: refactors SpecificationLoaderDefault
     new fff4237  ISIS-2250: incidentally, removes CglibEnhanced since not referenced anywhere
     new 4bd897c  ISIS-2250; adds ValueTypeProvider interface and no-op impl.
     new 5c154b1  ISIS-2250: introduces ValueTypeProvider, and beefs up ClassSubstitutor.
     new 7731712  ISIS-2250: special case treatment of FreeStandingList
     new d17d15d  ISIS-2250: and special case for Vector also (legacy collection class).
     new 596b90a  ISIS-2250: renames class is all
     new 27c56a5  ISIS-2250: debugs and fixes spec loader blocking issue.
     new 164120a  ISIS-2261: adds regex for config property
     new c4b506f  ISIS-2261: also uses Optional<X> for a couple of other config props
     new 6865b1a  ISIS-2261: sync adoc

The 11 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../examples/util/schema/CommonDtoUtils.java       |   2 +-
 .../isis/applib/util/schema/CommonDtoUtils.java    |   2 +-
 .../modules/config/examples/generated/Other.adoc   |   3 +-
 .../config/examples/generated/isis.reflector.adoc  |   2 +-
 .../generated/isis.reflector.validator.adoc        |   5 +
 .../generated/isis.viewer.restfulobjects.adoc      |   2 +-
 .../config/examples/generated/resteasy.adoc        |   9 --
 .../org/apache/isis/config/IsisConfiguration.java  |  19 ++-
 .../apache/isis/metamodel/IsisModuleMetamodel.java |  10 ++
 .../MethodPrefixBasedFacetFactoryAbstract.java     |  94 ++++++++------
 ...jectSpecIdFacetDerivedFromClassNameFactory.java |  14 +-
 .../ValueSemanticsProviderAndFacetAbstract.java    |  16 +--
 .../classsubstitutor/ClassSubstitutor.java         |   2 +-
 .../classsubstitutor/ClassSubstitutorAbstract.java |   3 +-
 .../classsubstitutor/ClassSubstitutorDefault.java  |   4 +
 .../ClassSubstitutorForCollections.java            |  66 ++++++++++
 .../classsubstitutor/ClassSubstitutorRegistry.java |  80 ++++++++++++
 .../isis/metamodel/spec/ObjectSpecification.java   |   2 +-
 .../metamodel/specloader/SpecificationLoader.java  |   2 +-
 .../specloader/SpecificationLoaderDefault.java     | 142 ++++++++++++++-------
 .../specloader/classsubstitutor/CglibEnhanced.java |  28 ----
 .../specloader/specimpl/FacetedMethodsBuilder.java |  12 +-
 .../specimpl/ObjectSpecificationAbstract.java      |   2 -
 .../specimpl/dflt/ObjectSpecificationDefault.java  |  14 +-
 .../validator/MetaModelValidatorAbstract.java      |   7 +-
 .../validator/MetaModelValidatorVisiting.java      |  16 +--
 .../metamodel/valuetypes/ValueTypeDefinition.java  |  27 ++++
 .../metamodel/valuetypes/ValueTypeProvider.java    |  16 +++
 .../valuetypes/ValueTypeProviderDefault.java       |  37 ++++++
 .../ValueTypeProviderForCollections.java           |  38 ++++++
 .../metamodel/valuetypes/ValueTypeRegistry.java    |  78 +++++++++++
 .../metamodel/MetaModelContext_forTesting.java     |   3 +-
 ...SpecIdFacetDerivedFromClassNameFactoryTest.java |   4 +
 .../JdoDiscriminatorAnnotationFacetFactory.java    |   6 +-
 .../session/init/IsisLocaleInitializer.java        |  35 +++--
 .../value/money/MoneyValueSemanticsProvider.java   |   6 +-
 36 files changed, 608 insertions(+), 200 deletions(-)
 create mode 100644 core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
 create mode 100644 core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorRegistry.java
 delete mode 100644 core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/classsubstitutor/CglibEnhanced.java
 create mode 100644 core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeDefinition.java
 create mode 100644 core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProvider.java
 create mode 100644 core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderDefault.java
 create mode 100644 core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderForCollections.java
 create mode 100644 core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeRegistry.java


[isis] 11/11: ISIS-2261: sync adoc

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 6865b1a3d702c991fdd2dd5944c15b311053e545
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Jan 9 18:23:46 2020 +0000

    ISIS-2261: sync adoc
---
 .../modules/applib-cm/examples/util/schema/CommonDtoUtils.java   | 2 +-
 .../src/main/doc/modules/config/examples/generated/Other.adoc    | 3 +--
 .../doc/modules/config/examples/generated/isis.reflector.adoc    | 2 +-
 .../config/examples/generated/isis.reflector.validator.adoc      | 5 +++++
 .../config/examples/generated/isis.viewer.restfulobjects.adoc    | 2 +-
 .../src/main/doc/modules/config/examples/generated/resteasy.adoc | 9 ---------
 6 files changed, 9 insertions(+), 14 deletions(-)

diff --git a/core/applib/src/main/doc/modules/applib-cm/examples/util/schema/CommonDtoUtils.java b/core/applib/src/main/doc/modules/applib-cm/examples/util/schema/CommonDtoUtils.java
index 179c420..4bb592d 100644
--- a/core/applib/src/main/doc/modules/applib-cm/examples/util/schema/CommonDtoUtils.java
+++ b/core/applib/src/main/doc/modules/applib-cm/examples/util/schema/CommonDtoUtils.java
@@ -67,7 +67,7 @@ public final class CommonDtoUtils {
     public static final Function<ParamDto, ValueType> PARAM_DTO_TO_TYPE = ParamDto::getType;
 
     // -- asValueType
-    private final static Map<Class<?>, ValueType> valueTypeByClass =
+    public final static Map<Class<?>, ValueType> valueTypeByClass =
             _Maps.unmodifiableEntries(
                     entry(String.class, ValueType.STRING),
                     entry(byte.class, ValueType.BYTE),
diff --git a/core/config/src/main/doc/modules/config/examples/generated/Other.adoc b/core/config/src/main/doc/modules/config/examples/generated/Other.adoc
index 42a7348..b132868 100644
--- a/core/config/src/main/doc/modules/config/examples/generated/Other.adoc
+++ b/core/config/src/main/doc/modules/config/examples/generated/Other.adoc
@@ -8,8 +8,7 @@
 
 | isis.locale
 | 
-|  Optional: set to override {@link Locale#getDefault()}  +
-{@code null} is allowed
+|  Set to override {@link Locale#getDefault()}
 
 | isis.objects.editing
 | 
diff --git a/core/config/src/main/doc/modules/config/examples/generated/isis.reflector.adoc b/core/config/src/main/doc/modules/config/examples/generated/isis.reflector.adoc
index dd2c13a..2d512c2 100644
--- a/core/config/src/main/doc/modules/config/examples/generated/isis.reflector.adoc
+++ b/core/config/src/main/doc/modules/config/examples/generated/isis.reflector.adoc
@@ -18,7 +18,7 @@ mode
 | isis.reflector.introspector. +
 parallelize
 |  true
-|  Whether to perform introspection and metamodel validation in parallel.
+|  Whether to perform introspection in parallel.
 
 | isis.reflector.introspector. +
 validate-incrementally
diff --git a/core/config/src/main/doc/modules/config/examples/generated/isis.reflector.validator.adoc b/core/config/src/main/doc/modules/config/examples/generated/isis.reflector.validator.adoc
index 0b4cde1..365bfe9 100644
--- a/core/config/src/main/doc/modules/config/examples/generated/isis.reflector.validator.adoc
+++ b/core/config/src/main/doc/modules/config/examples/generated/isis.reflector.validator.adoc
@@ -69,6 +69,11 @@ no-params-only
 | 
 
 | isis.reflector.validator. +
+parallelize
+|  true
+|  Whether to perform metamodel validation in parallel.
+
+| isis.reflector.validator. +
 mixins-only
 |  true
 | 
diff --git a/core/config/src/main/doc/modules/config/examples/generated/isis.viewer.restfulobjects.adoc b/core/config/src/main/doc/modules/config/examples/generated/isis.viewer.restfulobjects.adoc
index 907692f..8c68489 100644
--- a/core/config/src/main/doc/modules/config/examples/generated/isis.viewer.restfulobjects.adoc
+++ b/core/config/src/main/doc/modules/config/examples/generated/isis.viewer.restfulobjects.adoc
@@ -3,7 +3,7 @@ base-uri
 | 
 |  If left unset (the default), then the RO viewer will use the {@link javax.ws.rs.core.UriInfo} injected using  @link javax.ws.rs.core.Context}) to figure out the base Uri (used to render `href</code>s).  +
  This will be correct much of the time, but will almost certainly be wrong if there is a reverse proxy.   +
- If set, eg `https://dev.myapp.com</code>, then this value will be used instead. 
+ If set, eg `https://dev.myapp.com/</code>, then this value will be used instead. 
 
 | isis.viewer.restfulobjects. +
 gsoc2013.legacy-param-details
diff --git a/core/config/src/main/doc/modules/config/examples/generated/resteasy.adoc b/core/config/src/main/doc/modules/config/examples/generated/resteasy.adoc
index 8a8ac8b..644481d 100644
--- a/core/config/src/main/doc/modules/config/examples/generated/resteasy.adoc
+++ b/core/config/src/main/doc/modules/config/examples/generated/resteasy.adoc
@@ -6,15 +6,6 @@
 | 
 | 
 
-| resteasy.jaxrs.app. +
-registration
-| 
-| 
-
-| resteasy.jaxrs.default-path
-|  /restful
-|  Note that this is used rather than `resteasy.servlet.mapping.prefix</code> because there is _NO</i> implementation of {@link javax.ws.rs.core.Application}, so we rely on it being automatically created.
-
 | resteasy.resteasy-settings
 | 
 | 


[isis] 03/11: ISIS-2250; adds ValueTypeProvider interface and no-op impl.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 4bd897cd283d5cf9c3165b0238708c027165ca2c
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Jan 9 11:45:20 2020 +0000

    ISIS-2250; adds ValueTypeProvider interface and no-op impl.
---
 .../main/java/org/apache/isis/metamodel/IsisModuleMetamodel.java   | 2 ++
 .../org/apache/isis/metamodel/valuetypes/ValueTypeProvider.java    | 4 ++++
 .../apache/isis/metamodel/valuetypes/ValueTypeProviderBuiltIn.java | 7 +++++++
 3 files changed, 13 insertions(+)

diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/IsisModuleMetamodel.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/IsisModuleMetamodel.java
index 683d1eb..2b35fd3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/IsisModuleMetamodel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/IsisModuleMetamodel.java
@@ -45,6 +45,7 @@ import org.apache.isis.metamodel.services.user.UserServiceDefault;
 import org.apache.isis.metamodel.specloader.InjectorMethodEvaluatorDefault;
 import org.apache.isis.metamodel.specloader.ProgrammingModelServiceDefault;
 import org.apache.isis.metamodel.specloader.SpecificationLoaderDefault;
+import org.apache.isis.metamodel.valuetypes.ValueTypeProviderBuiltIn;
 import org.apache.isis.security.api.IsisModuleSecurityApi;
 
 @Configuration
@@ -61,6 +62,7 @@ import org.apache.isis.security.api.IsisModuleSecurityApi;
         // @Component's
         ProgrammingModelInitFilterDefault.class,
         ClassSubstitutorDefault.class,
+        ValueTypeProviderBuiltIn.class,
 
         // @Service's
         ObjectManagerDefault.class,
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProvider.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProvider.java
new file mode 100644
index 0000000..5a226f2
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProvider.java
@@ -0,0 +1,4 @@
+package org.apache.isis.metamodel.valuetypes;
+
+public interface ValueTypeProvider {
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderBuiltIn.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderBuiltIn.java
new file mode 100644
index 0000000..407381f
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderBuiltIn.java
@@ -0,0 +1,7 @@
+package org.apache.isis.metamodel.valuetypes;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class ValueTypeProviderBuiltIn implements ValueTypeProvider {
+}


[isis] 09/11: ISIS-2261: adds regex for config property

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 164120ad93e9fe0b1e43001f78300a5cb0e1a938
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Jan 9 17:35:08 2020 +0000

    ISIS-2261: adds regex for config property
---
 .../config/src/main/java/org/apache/isis/config/IsisConfiguration.java | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java b/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java
index 36be8c3..906a1e8 100644
--- a/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java
+++ b/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java
@@ -723,9 +723,10 @@ public class IsisConfiguration {
              * </p>
              *
              * <p>
-             * If set, eg <code>https://dev.myapp.com</code>, then this value will be used instead.
+             * If set, eg <code>https://dev.myapp.com/</code>, then this value will be used instead.
              * </p>
              */
+            @javax.validation.constraints.Pattern(regexp="^http[s]?://[^:]+?(:\\d+)?/$")
             private Optional<String> baseUri = Optional.empty();
             private final Gsoc2013 gsoc2013 = new Gsoc2013();
             @Data


[isis] 02/11: ISIS-2250: incidentally, removes CglibEnhanced since not referenced anywhere

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit fff4237c0d63c9e9d24bb527ec289da0c9705c57
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Jan 9 11:44:53 2020 +0000

    ISIS-2250: incidentally, removes CglibEnhanced since not referenced anywhere
---
 .../specloader/classsubstitutor/CglibEnhanced.java | 28 ----------------------
 1 file changed, 28 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/classsubstitutor/CglibEnhanced.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/classsubstitutor/CglibEnhanced.java
deleted file mode 100644
index 1acfeea..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/classsubstitutor/CglibEnhanced.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you 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
- *
- *        http://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.apache.isis.metamodel.specloader.classsubstitutor;
-
-/**
- * Marker interface to make it easy to spot classes that have been generated by
- * cg-lib.
- */
-public interface CglibEnhanced {
-
-}


[isis] 05/11: ISIS-2250: special case treatment of FreeStandingList

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 7731712a33dc8bfbe0ab914422a22b22aec72ce5
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Jan 9 15:26:30 2020 +0000

    ISIS-2250: special case treatment of FreeStandingList
    
    for class substitution
---
 .../services/classsubstitutor/ClassSubstitutorForCollections.java     | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
index b075ad9..209041e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
@@ -30,6 +30,7 @@ import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Component;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
+import org.apache.isis.metamodel.spec.FreeStandingList;
 
 import lombok.NonNull;
 
@@ -40,6 +41,9 @@ public class ClassSubstitutorForCollections implements ClassSubstitutor {
 
     @Override
     public Class<?> getClass(@lombok.NonNull @org.springframework.lang.NonNull Class<?> cls) {
+        if(FreeStandingList.class.isAssignableFrom(cls)) {
+            return FreeStandingList.class;
+        }
         if(List.class.isAssignableFrom(cls)) {
             return List.class;
         }


[isis] 10/11: ISIS-2261: also uses Optional for a couple of other config props

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit c4b506f68dd9ea20a7dc309adc80256a27562d64
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Jan 9 17:44:20 2020 +0000

    ISIS-2261: also uses Optional<X> for a couple of other config props
---
 .../org/apache/isis/config/IsisConfiguration.java  |  9 +++---
 .../ValueSemanticsProviderAndFacetAbstract.java    | 16 ++++------
 .../session/init/IsisLocaleInitializer.java        | 35 +++++++++++++---------
 .../value/money/MoneyValueSemanticsProvider.java   |  6 +++-
 4 files changed, 36 insertions(+), 30 deletions(-)

diff --git a/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java b/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java
index 906a1e8..565592d 100644
--- a/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java
+++ b/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java
@@ -88,10 +88,9 @@ public class IsisConfiguration {
     }
     
     /**
-     * Optional: set to override {@link Locale#getDefault()}
-     * <p>{@code null} is allowed
+     * Set to override {@link Locale#getDefault()}
      */
-    private String locale = null; //TODO no meta data yet ... https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-configuration-metadata.html#configuration-metadata-property-attributes
+    private Optional<String> locale = Optional.empty();
 
     private final Objects objects = new Objects();
     @Data
@@ -1217,10 +1216,10 @@ public class IsisConfiguration {
         @Data
         public static class Money {
             
-            private String currency = null;
+            private Optional<String> currency = Optional.empty();
 
             public String getCurrencyOrElse(String fallback) { 
-                return _Strings.isNotEmpty(getCurrency()) ? getCurrency() : fallback;
+                return getCurrency().filter(_Strings::isNotEmpty).orElse(fallback);
             }
         }
         
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/value/vsp/ValueSemanticsProviderAndFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/value/vsp/ValueSemanticsProviderAndFacetAbstract.java
index 5ad6233..be6f4f1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/value/vsp/ValueSemanticsProviderAndFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/value/vsp/ValueSemanticsProviderAndFacetAbstract.java
@@ -283,19 +283,15 @@ implements ValueSemanticsProvider<T>, EncoderDecoder<T>, Parser<T>, DefaultsProv
 
     protected NumberFormat determineNumberFormat(FormatIdentifier formatIdentifier) {
         final String formatRequired = getConfiguration()
-                .getValue().getFormatOrElse(formatIdentifier, null);  
-                
-        if (formatRequired != null) {
-            return new DecimalFormat(formatRequired);
-        } else {
-            return NumberFormat.getNumberInstance(findLocale());
-        }
+                .getValue().getFormatOrElse(formatIdentifier, null);
+
+        return formatRequired != null
+                ? new DecimalFormat(formatRequired)
+                : NumberFormat.getNumberInstance(findLocale());
     }
 
     private Locale findLocale() {
-        final String localeStr = getConfiguration().getLocale();
-        final Locale findLocale = LocaleUtil.findLocale(localeStr);
-        return findLocale != null ? findLocale : Locale.getDefault();
+        return getConfiguration().getLocale().map(LocaleUtil::findLocale).orElse(Locale.getDefault());
     }
 
     // //////////////////////////////////////////////////////////
diff --git a/core/runtime/src/main/java/org/apache/isis/runtime/session/init/IsisLocaleInitializer.java b/core/runtime/src/main/java/org/apache/isis/runtime/session/init/IsisLocaleInitializer.java
index 7380f55..6697fcd 100644
--- a/core/runtime/src/main/java/org/apache/isis/runtime/session/init/IsisLocaleInitializer.java
+++ b/core/runtime/src/main/java/org/apache/isis/runtime/session/init/IsisLocaleInitializer.java
@@ -20,6 +20,7 @@
 package org.apache.isis.runtime.session.init;
 
 import java.util.Locale;
+import java.util.Optional;
 
 import org.apache.isis.config.IsisConfiguration;
 
@@ -29,21 +30,27 @@ import lombok.extern.log4j.Log4j2;
 public class IsisLocaleInitializer {
 
     public void initLocale(final IsisConfiguration configuration) {
-        final String localeSpec = configuration.getLocale();
-        if (localeSpec != null) {
-            final int pos = localeSpec.indexOf('_');
-            Locale locale;
-            if (pos == -1) {
-                locale = new Locale(localeSpec, "");
-            } else {
-                final String language = localeSpec.substring(0, pos);
-                final String country = localeSpec.substring(pos + 1);
-                locale = new Locale(language, country);
-            }
-            Locale.setDefault(locale);
-            log.info("locale set to {}", locale);
-        }
+        final Optional<String> localeSpecOpt = configuration.getLocale();
+        localeSpecOpt.map(IsisLocaleInitializer::toLocale).ifPresent(IsisLocaleInitializer::setLocaleDefault);
         log.debug("locale is {}", Locale.getDefault());
     }
 
+    private static Locale toLocale(String localeSpec) {
+        final int pos = localeSpec.indexOf('_');
+        Locale locale;
+        if (pos == -1) {
+            locale = new Locale(localeSpec, "");
+        } else {
+            final String language = localeSpec.substring(0, pos);
+            final String country = localeSpec.substring(pos + 1);
+            locale = new Locale(language, country);
+        }
+        return locale;
+    }
+
+    private static void setLocaleDefault(Locale locale) {
+        Locale.setDefault(locale);
+        log.info("locale set to {}", locale);
+    }
+
 }
diff --git a/legacy/extensions/core/metamodel/src/main/java/org/apache/isis/legacy/metamodel/facets/value/money/MoneyValueSemanticsProvider.java b/legacy/extensions/core/metamodel/src/main/java/org/apache/isis/legacy/metamodel/facets/value/money/MoneyValueSemanticsProvider.java
index 64a7551..bc263d6 100644
--- a/legacy/extensions/core/metamodel/src/main/java/org/apache/isis/legacy/metamodel/facets/value/money/MoneyValueSemanticsProvider.java
+++ b/legacy/extensions/core/metamodel/src/main/java/org/apache/isis/legacy/metamodel/facets/value/money/MoneyValueSemanticsProvider.java
@@ -27,6 +27,7 @@ import java.util.Map;
 
 import org.apache.isis.applib.adapters.EncoderDecoder;
 import org.apache.isis.applib.adapters.Parser;
+import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.legacy.applib.value.Money;
 import org.apache.isis.metamodel.facetapi.Facet;
 import org.apache.isis.metamodel.facetapi.FacetHolder;
@@ -82,7 +83,10 @@ implements MoneyValueFacet {
     public MoneyValueSemanticsProvider(final FacetHolder holder) {
         super(type(), holder, Money.class, TYPICAL_LENGTH, -1, Immutability.IMMUTABLE, EqualByContent.HONOURED, DEFAULT_VALUE);
 
-        defaultCurrencyCode = getConfiguration().getValue().getMoney().getCurrencyOrElse(LOCAL_CURRENCY_CODE);        
+        defaultCurrencyCode =
+                getConfiguration().getValue().getMoney().getCurrency()
+                    .filter(_Strings::isNotEmpty)
+                    .orElse(LOCAL_CURRENCY_CODE);
     }
 
     // //////////////////////////////////////////////////////////////////


[isis] 04/11: ISIS-2250: introduces ValueTypeProvider, and beefs up ClassSubstitutor.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 5c154b13aea5f797d1cd93520504f7611ff042f4
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Jan 9 14:27:17 2020 +0000

    ISIS-2250: introduces ValueTypeProvider, and beefs up ClassSubstitutor.
    
    Each have a corresponding "Registry" that implements the chain-of-responsibility pattern around them.
    For now, ValueTypeProviderDefault delegates to CommonDtoUtils.
---
 .../isis/applib/util/schema/CommonDtoUtils.java    |  2 +-
 .../apache/isis/metamodel/IsisModuleMetamodel.java | 12 +++-
 ...jectSpecIdFacetDerivedFromClassNameFactory.java | 13 +++-
 .../classsubstitutor/ClassSubstitutor.java         |  2 +-
 .../classsubstitutor/ClassSubstitutorAbstract.java |  3 +-
 .../classsubstitutor/ClassSubstitutorDefault.java  |  4 ++
 .../ClassSubstitutorForCollections.java            | 57 +++++++++++++++
 .../classsubstitutor/ClassSubstitutorRegistry.java | 80 ++++++++++++++++++++++
 .../isis/metamodel/spec/ObjectSpecification.java   |  2 +-
 .../metamodel/specloader/SpecificationLoader.java  |  2 +-
 .../specloader/SpecificationLoaderDefault.java     | 46 +++++++++----
 .../specloader/specimpl/FacetedMethodsBuilder.java | 12 ++--
 .../specimpl/dflt/ObjectSpecificationDefault.java  | 14 ++--
 .../metamodel/valuetypes/ValueTypeDefinition.java  | 27 ++++++++
 .../metamodel/valuetypes/ValueTypeProvider.java    | 14 +++-
 .../valuetypes/ValueTypeProviderBuiltIn.java       |  7 --
 .../valuetypes/ValueTypeProviderDefault.java       | 37 ++++++++++
 .../ValueTypeProviderForCollections.java           | 38 ++++++++++
 .../metamodel/valuetypes/ValueTypeRegistry.java    | 78 +++++++++++++++++++++
 ...SpecIdFacetDerivedFromClassNameFactoryTest.java |  6 +-
 .../JdoDiscriminatorAnnotationFacetFactory.java    |  6 +-
 21 files changed, 411 insertions(+), 51 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java b/core/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java
index 179c420..4bb592d 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java
@@ -67,7 +67,7 @@ public final class CommonDtoUtils {
     public static final Function<ParamDto, ValueType> PARAM_DTO_TO_TYPE = ParamDto::getType;
 
     // -- asValueType
-    private final static Map<Class<?>, ValueType> valueTypeByClass =
+    public final static Map<Class<?>, ValueType> valueTypeByClass =
             _Maps.unmodifiableEntries(
                     entry(String.class, ValueType.STRING),
                     entry(byte.class, ValueType.BYTE),
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/IsisModuleMetamodel.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/IsisModuleMetamodel.java
index 2b35fd3..42a9bbf 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/IsisModuleMetamodel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/IsisModuleMetamodel.java
@@ -30,6 +30,8 @@ import org.apache.isis.metamodel.services.ServiceInjectorDefault;
 import org.apache.isis.metamodel.services.appfeat.ApplicationFeatureFactory;
 import org.apache.isis.metamodel.services.appfeat.ApplicationFeatureRepositoryDefault;
 import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorDefault;
+import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorRegistry;
+import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorForCollections;
 import org.apache.isis.metamodel.services.events.MetamodelEventService;
 import org.apache.isis.metamodel.services.events.MetamodelEventSupport_Spring;
 import org.apache.isis.metamodel.services.exceprecog.ExceptionRecognizerDocDefault;
@@ -45,7 +47,9 @@ import org.apache.isis.metamodel.services.user.UserServiceDefault;
 import org.apache.isis.metamodel.specloader.InjectorMethodEvaluatorDefault;
 import org.apache.isis.metamodel.specloader.ProgrammingModelServiceDefault;
 import org.apache.isis.metamodel.specloader.SpecificationLoaderDefault;
-import org.apache.isis.metamodel.valuetypes.ValueTypeProviderBuiltIn;
+import org.apache.isis.metamodel.valuetypes.ValueTypeProviderDefault;
+import org.apache.isis.metamodel.valuetypes.ValueTypeProviderForCollections;
+import org.apache.isis.metamodel.valuetypes.ValueTypeRegistry;
 import org.apache.isis.security.api.IsisModuleSecurityApi;
 
 @Configuration
@@ -62,7 +66,11 @@ import org.apache.isis.security.api.IsisModuleSecurityApi;
         // @Component's
         ProgrammingModelInitFilterDefault.class,
         ClassSubstitutorDefault.class,
-        ValueTypeProviderBuiltIn.class,
+        ClassSubstitutorForCollections.class,
+        ClassSubstitutorRegistry.class,
+        ValueTypeProviderDefault.class,
+        ValueTypeProviderForCollections.class,
+        ValueTypeRegistry.class,
 
         // @Service's
         ObjectManagerDefault.class,
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
index efb0ae7..9807ab2 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
@@ -19,6 +19,7 @@
 
 package org.apache.isis.metamodel.facets.object.objectspecid.classname;
 
+import java.util.Collections;
 import java.util.stream.Stream;
 
 import javax.inject.Inject;
@@ -34,8 +35,8 @@ import org.apache.isis.metamodel.facets.ObjectSpecIdFacetFactory;
 import org.apache.isis.metamodel.facets.object.domainservice.DomainServiceFacet;
 import org.apache.isis.metamodel.facets.object.objectspecid.ObjectSpecIdFacet;
 import org.apache.isis.metamodel.progmodel.ProgrammingModel;
-import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutor;
 import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorDefault;
+import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorRegistry;
 import org.apache.isis.metamodel.spec.ObjectSpecification;
 import org.apache.isis.metamodel.spec.feature.Contributed;
 import org.apache.isis.metamodel.spec.feature.ObjectAction;
@@ -49,11 +50,17 @@ extends FacetFactoryAbstract
 implements MetaModelRefiner, ObjectSpecIdFacetFactory {
 
     @Inject
-    private ClassSubstitutor classSubstitutor = new ClassSubstitutorDefault(); // default for testing purposes only, overwritten in prod
+    private ClassSubstitutorRegistry classSubstitutorRegistry;
+
 
     public ObjectSpecIdFacetDerivedFromClassNameFactory() {
         super(FeatureType.OBJECTS_ONLY);
     }
+    // default for testing purposes only, overwritten in prod
+    public ObjectSpecIdFacetDerivedFromClassNameFactory(ClassSubstitutorRegistry classSubstitutorRegistry) {
+        this();
+        this.classSubstitutorRegistry = classSubstitutorRegistry;
+    }
 
     @Override
     public void process(final ProcessObjectSpecIdContext processClassContext) {
@@ -63,7 +70,7 @@ implements MetaModelRefiner, ObjectSpecIdFacetFactory {
             return;
         }
         final Class<?> cls = processClassContext.getCls();
-        final Class<?> substitutedClass = classSubstitutor.getClass(cls);
+        final Class<?> substitutedClass = classSubstitutorRegistry.getClass(cls);
         if(substitutedClass == null) {
             return;
         }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutor.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutor.java
index 1059824..edb2bf3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutor.java
@@ -24,5 +24,5 @@ package org.apache.isis.metamodel.services.classsubstitutor;
  */
 public interface ClassSubstitutor {
 
-    Class<?> getClass(Class<?> type);
+    Class<?> getClass(@lombok.NonNull @org.springframework.lang.NonNull Class<?> cls);
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorAbstract.java
index 8ed9c73..e3a32c1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorAbstract.java
@@ -34,7 +34,7 @@ public abstract class ClassSubstitutorAbstract implements ClassSubstitutor {
     @Override
     public Class<?> getClass(final Class<?> cls) {
 
-        if (cls == null) {
+        if(cls == null) {
             return null;
         }
 
@@ -59,6 +59,7 @@ public abstract class ClassSubstitutorAbstract implements ClassSubstitutor {
             return superclass;
         }
         if (ClassUtil.directlyImplements(cls, ProxyEnhanced.class)) {
+            // REVIEW: arguably this should now go back to the ClassSubstitorRegistry
             return getClass(cls.getSuperclass());
         }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorDefault.java
index 32f0bd2..c383dfe 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorDefault.java
@@ -21,10 +21,14 @@ package org.apache.isis.metamodel.services.classsubstitutor;
 
 import javax.inject.Named;
 
+import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Component;
 
+import org.apache.isis.applib.annotation.OrderPrecedence;
+
 @Component
 @Named("isisMetaModel.ClassSubstitutorDefault")
+@Order(OrderPrecedence.MIDPOINT)
 public class ClassSubstitutorDefault extends ClassSubstitutorAbstract {
 
     public ClassSubstitutorDefault() {
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
new file mode 100644
index 0000000..b075ad9
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
@@ -0,0 +1,57 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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
+ *
+ *        http://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.apache.isis.metamodel.services.classsubstitutor;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+
+import javax.inject.Named;
+
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import org.apache.isis.applib.annotation.OrderPrecedence;
+
+import lombok.NonNull;
+
+@Component
+@Named("isisMetaModel.ClassSubstitutorUnmodifiableCollections")
+@Order(OrderPrecedence.MIDPOINT + 1)
+public class ClassSubstitutorForCollections implements ClassSubstitutor {
+
+    @Override
+    public Class<?> getClass(@lombok.NonNull @org.springframework.lang.NonNull Class<?> cls) {
+        if(List.class.isAssignableFrom(cls)) {
+            return List.class;
+        }
+        if(SortedSet.class.isAssignableFrom(cls)) {
+            return SortedSet.class;
+        }
+        if(Set.class.isAssignableFrom(cls)) {
+            return Set.class;
+        }
+        if(Collection.class.isAssignableFrom(cls)) {
+            return Collection.class;
+        }
+        return cls;
+    }
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorRegistry.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorRegistry.java
new file mode 100644
index 0000000..d2d5cff
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorRegistry.java
@@ -0,0 +1,80 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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
+ *
+ *        http://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.apache.isis.metamodel.services.classsubstitutor;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import org.apache.isis.applib.annotation.OrderPrecedence;
+import org.apache.isis.commons.internal.collections._Maps;
+
+/**
+ * Aggregates all {@link ClassSubstitutor}s.
+ */
+@Component
+@Named("isisMetaModel.ClassSubstitutorRegistry")
+@Order(OrderPrecedence.MIDPOINT)
+public class ClassSubstitutorRegistry {
+
+    private final List<ClassSubstitutor> classSubstitutors;
+
+    @Inject
+    public ClassSubstitutorRegistry(final List<ClassSubstitutor> classSubstitutors) {
+        this.classSubstitutors = classSubstitutors;
+    }
+
+    private final Map<Class<?>, Optional<Class<?>>> cache = _Maps.newHashMap();
+
+    // TODO: it would be preferable to return an Optional here.
+    public Class<?> getClass(final Class<?> originalClass) {
+        if(originalClass == null) {
+            return null;
+        }
+
+        Optional<Class<?>> substitutedClass = cache.get(originalClass);
+
+
+        cacheMiss:
+        //noinspection OptionalAssignedToNull
+        if(substitutedClass == null) {
+            // don't yet know if this class needs to be substituted
+            for (ClassSubstitutor classSubstitutor : classSubstitutors) {
+                final Class<?> substitutedType = classSubstitutor.getClass(originalClass);
+                if(substitutedType != originalClass) {
+                    // one of the substitutors has made a substitution
+                    // (though note, it might have substituted it with null).
+                    substitutedClass = Optional.ofNullable(substitutedType);
+                    break cacheMiss;
+                }
+            }
+            // no substitution
+            substitutedClass = Optional.of(originalClass);
+            cache.put(originalClass, substitutedClass);
+        }
+        return substitutedClass.orElse(null);
+    }
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/ObjectSpecification.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/ObjectSpecification.java
index 8c3c24b..ae17d36 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/ObjectSpecification.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/ObjectSpecification.java
@@ -113,7 +113,7 @@ ObjectAssociationContainer, Hierarchical,  DefaultProvider {
      * <p>
      * This will typically be the value of the {@link DomainObject#objectType()} annotation attribute.
      * If none has been specified then will default to the fully qualified class name (with
-     * {@link ClassSubstitutor class name substituted} if necessary to allow for runtime bytecode enhancement.
+     * {@link org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorRegistry class name substituted} if necessary to allow for runtime bytecode enhancement.
      *
      * <p>
      * The {@link ObjectSpecification} can be retrieved using {@link SpecificationLoader#lookupBySpecIdO(ObjectSpecId)}.
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoader.java
index a5b132b..fd645cb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoader.java
@@ -94,7 +94,7 @@ public interface SpecificationLoader {
      *
      * <p>
      * It is possible for this method to return <tt>null</tt>, for example if
-     * the configured {@link ClassSubstitutor} has filtered out the class.
+     * any of the configured {@link ClassSubstitutor}s has filtered out the class.
      * 
      * @return {@code null} if {@code domainType==null}, or if the type should be ignored.
      */
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java
index 59f3d68..d45eb44 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java
@@ -20,6 +20,7 @@ package org.apache.isis.metamodel.specloader;
 
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Objects;
 import java.util.function.Consumer;
 
@@ -36,7 +37,6 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.registry.ServiceRegistry;
-import org.apache.isis.applib.util.schema.CommonDtoUtils;
 import org.apache.isis.commons.internal.base._Blackhole;
 import org.apache.isis.commons.internal.base._Lazy;
 import org.apache.isis.commons.internal.base._Timing;
@@ -54,6 +54,8 @@ import org.apache.isis.metamodel.progmodel.ProgrammingModelService;
 import org.apache.isis.metamodel.progmodels.dflt.ProgrammingModelFacetsJava8;
 import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutor;
 import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorDefault;
+import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorRegistry;
+import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorForCollections;
 import org.apache.isis.metamodel.spec.FreeStandingList;
 import org.apache.isis.metamodel.spec.ObjectSpecId;
 import org.apache.isis.metamodel.spec.ObjectSpecification;
@@ -65,6 +67,8 @@ import org.apache.isis.metamodel.specloader.specimpl.dflt.ObjectSpecificationDef
 import org.apache.isis.metamodel.specloader.specimpl.standalonelist.ObjectSpecificationOnStandaloneList;
 import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorAbstract;
 import org.apache.isis.metamodel.specloader.validator.ValidationFailures;
+import org.apache.isis.metamodel.valuetypes.ValueTypeProviderDefault;
+import org.apache.isis.metamodel.valuetypes.ValueTypeRegistry;
 
 import static org.apache.isis.commons.internal.base._With.requires;
 
@@ -99,7 +103,8 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
     private final IsisSystemEnvironment isisSystemEnvironment;
     private final ServiceRegistry serviceRegistry;
     private final IsisBeanTypeRegistryHolder isisBeanTypeRegistryHolder;
-    private final ClassSubstitutor classSubstitutor = new ClassSubstitutorDefault();
+    private final ClassSubstitutorRegistry classSubstitutorRegistry;
+    private final ValueTypeRegistry valueTypeRegistry;
 
     private final ProgrammingModel programmingModel;
     private final PostProcessor postProcessor;
@@ -108,8 +113,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
 
     private FacetProcessor facetProcessor;
 
-    private final SpecificationCacheDefault<ObjectSpecification> cache = 
-            new SpecificationCacheDefault<>();
+    private final SpecificationCacheDefault<ObjectSpecification> cache = new SpecificationCacheDefault<>();
 
     /**
      * We only ever mark the metamodel as fully introspected if in {@link #isFullIntrospect() full} introspection mode.
@@ -123,13 +127,15 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
             final IsisConfiguration isisConfiguration,
             final IsisSystemEnvironment isisSystemEnvironment,
             final ServiceRegistry serviceRegistry,
-            final IsisBeanTypeRegistryHolder isisBeanTypeRegistryHolder) {
+            final IsisBeanTypeRegistryHolder isisBeanTypeRegistryHolder,
+            final ValueTypeRegistry valueTypeRegistry,
+            final ClassSubstitutorRegistry classSubstitutorRegistry) {
         this(
                 programmingModelService.getProgrammingModel(),
                 isisConfiguration,
                 isisSystemEnvironment,
                 serviceRegistry,
-                isisBeanTypeRegistryHolder);
+                isisBeanTypeRegistryHolder, valueTypeRegistry, classSubstitutorRegistry);
     }
 
     SpecificationLoaderDefault(
@@ -137,13 +143,17 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
             final IsisConfiguration isisConfiguration,
             final IsisSystemEnvironment isisSystemEnvironment,
             final ServiceRegistry serviceRegistry,
-            final IsisBeanTypeRegistryHolder isisBeanTypeRegistryHolder) {
+            final IsisBeanTypeRegistryHolder isisBeanTypeRegistryHolder,
+            final ValueTypeRegistry valueTypeRegistry,
+            final ClassSubstitutorRegistry classSubstitutorRegistry) {
         this.programmingModel = programmingModel;
         this.postProcessor = new PostProcessor(programmingModel);
         this.isisConfiguration = isisConfiguration;
         this.isisSystemEnvironment = isisSystemEnvironment;
         this.serviceRegistry = serviceRegistry;
         this.isisBeanTypeRegistryHolder = isisBeanTypeRegistryHolder;
+        this.valueTypeRegistry = valueTypeRegistry;
+        this.classSubstitutorRegistry = classSubstitutorRegistry;
     }
 
     /** JUnit Test Support */
@@ -154,7 +164,11 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
             final ProgrammingModel programmingModel,
             final IsisBeanTypeRegistryHolder isisBeanTypeRegistryHolder) {
 
-        val instance = new SpecificationLoaderDefault(programmingModel, isisConfiguration, isisSystemEnvironment, serviceRegistry, isisBeanTypeRegistryHolder);
+        val instance = new SpecificationLoaderDefault(
+                programmingModel, isisConfiguration, isisSystemEnvironment,
+                serviceRegistry, isisBeanTypeRegistryHolder,
+                new ValueTypeRegistry(Collections.singletonList(new ValueTypeProviderDefault())),
+                new ClassSubstitutorRegistry(Collections.unmodifiableList(Arrays.asList(new ClassSubstitutorDefault(), new ClassSubstitutorForCollections()))));
 
         instance.metaModelContext = serviceRegistry.lookupServiceElseFail(MetaModelContext.class);
         instance.facetProcessor = new FacetProcessor(programmingModel, instance.metaModelContext);
@@ -192,9 +206,11 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
         val domainServiceSpecs = _Lists.<ObjectSpecification>newArrayList();
         val domainObjectSpecs = _Lists.<ObjectSpecification>newArrayList();
 
-        CommonDtoUtils.VALUE_TYPES.forEach(type->{
-            val spec = loadSpecification(type, IntrospectionState.NOT_INTROSPECTED);
-            if(spec!=null) scannedSpecs.add(spec);
+        valueTypeRegistry.classes().forEach(clazz -> {
+            val spec = loadSpecification(clazz, IntrospectionState.NOT_INTROSPECTED);
+            if(spec!=null) {
+                scannedSpecs.add(spec);
+            }
         });
 
         log.info(" - categorizing types from class-path scan");
@@ -315,7 +331,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
     public boolean loadSpecifications(Class<?>... domainTypes) {
         // ensure that all types are loadable
         if (Arrays.stream(domainTypes)
-                .map(classSubstitutor::getClass)
+                .map(classSubstitutorRegistry::getClass)
                 .anyMatch(Objects::isNull)) {
             return false;
         }
@@ -334,7 +350,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
 
         requires(upTo, "upTo");
 
-        val substitutedType = classSubstitutor.getClass(type);
+        val substitutedType = classSubstitutorRegistry.getClass(type);
         if (substitutedType == null) {
             return null;
         }
@@ -437,7 +453,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
                             facetProcessor,
                             managedBeanNameIfAny.orElse(null),
                             postProcessor,
-                            classSubstitutor);
+                            classSubstitutorRegistry);
         }
 
         return objectSpec;
@@ -474,7 +490,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
 
     private void invalidateCache(final Class<?> cls) {
 
-        val substitutedType = classSubstitutor.getClass(cls);
+        val substitutedType = classSubstitutorRegistry.getClass(cls);
 
         ObjectSpecification spec = 
                 loadSpecification(substitutedType, IntrospectionState.TYPE_AND_MEMBERS_INTROSPECTED);
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/FacetedMethodsBuilder.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
index 08c3c07..98c92de 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
@@ -52,7 +52,7 @@ import org.apache.isis.metamodel.facets.FacetedMethodParameter;
 import org.apache.isis.metamodel.facets.actcoll.typeof.TypeOfFacet;
 import org.apache.isis.metamodel.facets.object.facets.FacetsFacet;
 import org.apache.isis.metamodel.facets.object.mixin.MixinFacet;
-import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutor;
+import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorRegistry;
 import org.apache.isis.metamodel.specloader.SpecificationLoader;
 import org.apache.isis.metamodel.specloader.facetprocessor.FacetProcessor;
 import org.apache.isis.metamodel.specloader.traverser.TypeExtractorMethodReturn;
@@ -139,7 +139,7 @@ public class FacetedMethodsBuilder {
 
     private final FacetProcessor facetProcessor;
 
-    private final ClassSubstitutor classSubstitutor;
+    private final ClassSubstitutorRegistry classSubstitutorRegistry;
 
     private final SpecificationLoader specificationLoader;
 
@@ -153,14 +153,14 @@ public class FacetedMethodsBuilder {
     public FacetedMethodsBuilder(
             final ObjectSpecificationAbstract inspectedTypeSpec,
             final FacetProcessor facetProcessor,
-            final ClassSubstitutor classSubstitutor) {
+            final ClassSubstitutorRegistry classSubstitutorRegistry) {
 
         if (log.isDebugEnabled()) {
             log.debug("creating JavaIntrospector for {}", inspectedTypeSpec.getFullIdentifier());
         }
 
         this.facetProcessor = facetProcessor;
-        this.classSubstitutor = classSubstitutor;
+        this.classSubstitutorRegistry = classSubstitutorRegistry;
 
         val mmContext = inspectedTypeSpec.getMetaModelContext();
 
@@ -315,7 +315,7 @@ public class FacetedMethodsBuilder {
             facetedMethod.setType(elementType);
 
             // skip if class substitutor says so.
-            if (classSubstitutor.getClass(elementType) == null) {
+            if (classSubstitutorRegistry.getClass(elementType) == null) {
                 continue;
             }
 
@@ -333,7 +333,7 @@ public class FacetedMethodsBuilder {
             final Class<?> returnType = accessorMethod.getReturnType();
 
             // skip if class strategy says so.
-            if (classSubstitutor.getClass(returnType) == null) {
+            if (classSubstitutorRegistry.getClass(returnType) == null) {
                 continue;
             }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index 14b38aa..ebf4709 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -33,8 +33,6 @@ import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Lazy;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Maps;
-import org.apache.isis.commons.internal.exceptions._Exceptions;
-import org.apache.isis.commons.internal.ioc.BeanSort;
 import org.apache.isis.metamodel.commons.StringExtensions;
 import org.apache.isis.metamodel.commons.ToString;
 import org.apache.isis.metamodel.context.MetaModelContext;
@@ -53,7 +51,7 @@ import org.apache.isis.metamodel.facets.object.plural.inferred.PluralFacetInferr
 import org.apache.isis.metamodel.facets.object.value.ValueFacet;
 import org.apache.isis.metamodel.facets.object.viewmodel.ViewModelFacet;
 import org.apache.isis.metamodel.facets.object.wizard.WizardFacet;
-import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutor;
+import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorRegistry;
 import org.apache.isis.metamodel.spec.ActionType;
 import org.apache.isis.metamodel.spec.ElementSpecificationProvider;
 import org.apache.isis.metamodel.spec.ManagedObject;
@@ -93,7 +91,7 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
     private Map<Method, ObjectMember> membersByMethod = null;
 
     private final FacetedMethodsBuilder facetedMethodsBuilder;
-    private final ClassSubstitutor classSubstitutor;
+    private final ClassSubstitutorRegistry classSubstitutorRegistry;
 
 
     /**
@@ -107,15 +105,15 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
             final FacetProcessor facetProcessor,
             final String nameIfIsManagedBean,
             final PostProcessor postProcessor,
-            final ClassSubstitutor classSubstitutor) {
+            final ClassSubstitutorRegistry classSubstitutorRegistry) {
         
         super(correspondingClass, determineShortName(correspondingClass), facetProcessor, postProcessor);
 
         setMetaModelContext(metaModelContext);
 
         this.nameIfIsManagedBean = nameIfIsManagedBean;
-        this.facetedMethodsBuilder = new FacetedMethodsBuilder(this, facetProcessor, classSubstitutor);
-        this.classSubstitutor = classSubstitutor;
+        this.facetedMethodsBuilder = new FacetedMethodsBuilder(this, facetProcessor, classSubstitutorRegistry);
+        this.classSubstitutorRegistry = classSubstitutorRegistry;
 
         facetProcessor.processObjectSpecId(correspondingClass, this);
         
@@ -165,7 +163,7 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
         final Class<?>[] interfaceTypes = getCorrespondingClass().getInterfaces();
         final List<ObjectSpecification> interfaceSpecList = _Lists.newArrayList();
         for (val interfaceType : interfaceTypes) {
-            val substitutedInterfaceType = classSubstitutor.getClass(interfaceType);
+            val substitutedInterfaceType = classSubstitutorRegistry.getClass(interfaceType);
             if (substitutedInterfaceType != null) {
                 val interfaceSpec = getSpecificationLoader().loadSpecification(substitutedInterfaceType);
                 interfaceSpecList.add(interfaceSpec);
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeDefinition.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeDefinition.java
new file mode 100644
index 0000000..895be43
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeDefinition.java
@@ -0,0 +1,27 @@
+package org.apache.isis.metamodel.valuetypes;
+
+import java.util.Map;
+
+import org.apache.isis.schema.common.v1.ValueType;
+
+import lombok.Data;
+
+@Data
+public class ValueTypeDefinition {
+
+    public static ValueTypeDefinition collection(Class<?> clazz) {
+        return new ValueTypeDefinition(clazz, ValueType.COLLECTION);
+    }
+    public static ValueTypeDefinition of(Class<?> clazz, ValueType valueType) {
+        return new ValueTypeDefinition(clazz, valueType);
+    }
+    public static ValueTypeDefinition from(final Map.Entry<Class<?>, ValueType> entry) {
+        return new ValueTypeDefinition(entry.getKey(), entry.getValue());
+    }
+    private ValueTypeDefinition(Class<?> clazz, ValueType valueType) {
+        this.clazz = clazz;
+        this.valueType = valueType;
+    }
+    private final Class<?> clazz;
+    private final ValueType valueType;
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProvider.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProvider.java
index 5a226f2..68a61e2 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProvider.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProvider.java
@@ -1,4 +1,16 @@
 package org.apache.isis.metamodel.valuetypes;
 
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.isis.schema.common.v1.ValueType;
+
 public interface ValueTypeProvider {
-}
+
+    Collection<ValueTypeDefinition> definitions();
+
+
+
+}
\ No newline at end of file
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderBuiltIn.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderBuiltIn.java
deleted file mode 100644
index 407381f..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderBuiltIn.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.apache.isis.metamodel.valuetypes;
-
-import org.springframework.stereotype.Component;
-
-@Component
-public class ValueTypeProviderBuiltIn implements ValueTypeProvider {
-}
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderDefault.java
new file mode 100644
index 0000000..11fe39c
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderDefault.java
@@ -0,0 +1,37 @@
+package org.apache.isis.metamodel.valuetypes;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.inject.Named;
+
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import org.apache.isis.applib.annotation.OrderPrecedence;
+import org.apache.isis.applib.util.schema.CommonDtoUtils;
+import org.apache.isis.schema.common.v1.ValueType;
+
+@Component
+@Named("isisMetaModel.ValueTypeProviderBuiltIn")
+@Order(OrderPrecedence.MIDPOINT)
+public class ValueTypeProviderDefault implements ValueTypeProvider {
+
+    private final Map<Class<?>, ValueTypeDefinition> definitions =
+            from(CommonDtoUtils.valueTypeByClass);
+
+    private static Map<Class<?>, ValueTypeDefinition> from(final Map<Class<?>, ValueType> valueTypeByClass) {
+        final Map<Class<?>, ValueTypeDefinition> map = new LinkedHashMap<>();
+        valueTypeByClass.entrySet()
+                .forEach(entry -> map.put(entry.getKey(), ValueTypeDefinition.from(entry)));
+        return map;
+    }
+
+    @Override
+    public Collection<ValueTypeDefinition> definitions() {
+        return definitions.values();
+    }
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderForCollections.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderForCollections.java
new file mode 100644
index 0000000..0af096f
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeProviderForCollections.java
@@ -0,0 +1,38 @@
+package org.apache.isis.metamodel.valuetypes;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.SortedSet;
+
+import javax.inject.Named;
+
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import org.apache.isis.applib.annotation.OrderPrecedence;
+import org.apache.isis.applib.util.schema.CommonDtoUtils;
+import org.apache.isis.metamodel.spec.FreeStandingList;
+import org.apache.isis.schema.common.v1.ValueType;
+
+@Component
+@Named("isisMetaModel.ValueTypeProviderCollections")
+@Order(OrderPrecedence.MIDPOINT)
+public class ValueTypeProviderForCollections implements ValueTypeProvider {
+
+    @Override
+    public Collection<ValueTypeDefinition> definitions() {
+        return Collections.unmodifiableList(Arrays.asList(
+                    ValueTypeDefinition.collection(List.class),
+                    ValueTypeDefinition.collection(Set.class),
+                    ValueTypeDefinition.collection(SortedSet.class),
+                    ValueTypeDefinition.collection(FreeStandingList.class)
+                ));
+    }
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeRegistry.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeRegistry.java
new file mode 100644
index 0000000..dc617f9
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/valuetypes/ValueTypeRegistry.java
@@ -0,0 +1,78 @@
+package org.apache.isis.metamodel.valuetypes;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import org.apache.isis.applib.annotation.OrderPrecedence;
+import org.apache.isis.schema.common.v1.ValueType;
+
+import lombok.val;
+
+@Component
+@Named("isisMetaModel.ValueTypeRegistry")
+@Order(OrderPrecedence.MIDPOINT)
+public class ValueTypeRegistry {
+
+    private final List<ValueTypeProvider> valueTypeProviders;
+    private final Map<Class<?>, Optional<ValueTypeDefinition>> definitionByClazz;
+
+    @Inject
+    public ValueTypeRegistry(
+            final List<ValueTypeProvider> valueTypeProviders) {
+        this.valueTypeProviders = valueTypeProviders;
+        this.definitionByClazz = Collections.unmodifiableMap(aggregate(valueTypeProviders));
+    }
+
+    static Map<Class<?>, Optional<ValueTypeDefinition>> aggregate(
+            final List<ValueTypeProvider> valueTypeProviders) {
+
+        final Map<Class<?>, Optional<ValueTypeDefinition>> map = new LinkedHashMap<>();
+        for (ValueTypeProvider valueTypeProvider : valueTypeProviders) {
+            final Collection<ValueTypeDefinition> valueTypeDefinitions = valueTypeProvider.definitions();
+            valueTypeDefinitions
+                    .forEach(valueTypeDefinition -> {
+                        map.put(valueTypeDefinition.getClazz(), Optional.of(valueTypeDefinition));
+                    });
+        }
+        return map;
+    }
+
+    public ValueType asValueType(final Class<?> clazz) {
+        return definitionByClazz.getOrDefault(clazz, Optional.empty())
+                .map(ValueTypeDefinition::getValueType)
+                .orElse(fallback(clazz));
+    }
+
+    private static ValueType fallback(final Class<?> clazz) {
+        if (clazz!=null && clazz.isEnum()) {
+            return ValueType.ENUM;
+        }
+        // assume reference otherwise
+        return ValueType.REFERENCE;
+    }
+
+    public Stream<Class<?>> classes() {
+        val classes = new LinkedHashSet<Class<?>>();
+        valueTypeProviders.stream()
+                .map(ValueTypeProvider::definitions)
+                .forEach(definitions -> {
+                    definitions.stream()
+                            .map(ValueTypeDefinition::getClazz)
+                            .forEach(classes::add);
+                });
+        return classes.stream();
+    }
+
+}
\ No newline at end of file
diff --git a/core/metamodel/src/test/java/org/apache/isis/metamodel/facets/object/objectspecid/ObjectSpecIdFacetDerivedFromClassNameFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/metamodel/facets/object/objectspecid/ObjectSpecIdFacetDerivedFromClassNameFactoryTest.java
index 6c7c576..3a9c54d 100644
--- a/core/metamodel/src/test/java/org/apache/isis/metamodel/facets/object/objectspecid/ObjectSpecIdFacetDerivedFromClassNameFactoryTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/metamodel/facets/object/objectspecid/ObjectSpecIdFacetDerivedFromClassNameFactoryTest.java
@@ -19,6 +19,8 @@
 
 package org.apache.isis.metamodel.facets.object.objectspecid;
 
+import java.util.Collections;
+
 import org.datanucleus.testing.dom.CustomerAsProxiedByDataNucleus;
 import org.junit.Before;
 import org.junit.Test;
@@ -32,6 +34,8 @@ import org.apache.isis.metamodel.facets.AbstractFacetFactoryJUnit4TestCase;
 import org.apache.isis.metamodel.facets.ObjectSpecIdFacetFactory;
 import org.apache.isis.metamodel.facets.object.objectspecid.classname.ObjectSpecIdFacetDerivedFromClassName;
 import org.apache.isis.metamodel.facets.object.objectspecid.classname.ObjectSpecIdFacetDerivedFromClassNameFactory;
+import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorDefault;
+import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorRegistry;
 import org.apache.isis.metamodel.spec.ObjectSpecId;
 
 public class ObjectSpecIdFacetDerivedFromClassNameFactoryTest extends AbstractFacetFactoryJUnit4TestCase {
@@ -40,7 +44,7 @@ public class ObjectSpecIdFacetDerivedFromClassNameFactoryTest extends AbstractFa
 
     @Before
     public void setUp() throws Exception {
-        facetFactory = new ObjectSpecIdFacetDerivedFromClassNameFactory();
+        facetFactory = new ObjectSpecIdFacetDerivedFromClassNameFactory(new ClassSubstitutorRegistry(Collections.singletonList( new ClassSubstitutorDefault())));
     }
 
     public static class Customer {
diff --git a/core/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/metamodel/facets/object/discriminator/JdoDiscriminatorAnnotationFacetFactory.java b/core/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/metamodel/facets/object/discriminator/JdoDiscriminatorAnnotationFacetFactory.java
index 0e24e43..073f23c 100644
--- a/core/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/metamodel/facets/object/discriminator/JdoDiscriminatorAnnotationFacetFactory.java
+++ b/core/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/metamodel/facets/object/discriminator/JdoDiscriminatorAnnotationFacetFactory.java
@@ -31,7 +31,7 @@ import org.apache.isis.metamodel.facets.FacetFactoryAbstract;
 import org.apache.isis.metamodel.facets.ObjectSpecIdFacetFactory;
 import org.apache.isis.metamodel.facets.object.objectspecid.ObjectSpecIdFacet;
 import org.apache.isis.metamodel.facets.object.objectspecid.classname.ObjectSpecIdFacetDerivedFromClassName;
-import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutor;
+import org.apache.isis.metamodel.services.classsubstitutor.ClassSubstitutorRegistry;
 import org.apache.isis.persistence.jdo.datanucleus5.metamodel.JdoMetamodelUtil;
 
 public class JdoDiscriminatorAnnotationFacetFactory
@@ -39,7 +39,7 @@ extends FacetFactoryAbstract
 implements ObjectSpecIdFacetFactory {
 
     @Inject
-    private ClassSubstitutor classSubstitutor;
+    private ClassSubstitutorRegistry classSubstitutorRegistry;
 
     public JdoDiscriminatorAnnotationFacetFactory() {
         super(FeatureType.OBJECTS_ONLY);
@@ -66,7 +66,7 @@ implements ObjectSpecIdFacetFactory {
             facet = new ObjectSpecIdFacetInferredFromJdoDiscriminatorValueAnnotation(
                     annotationValue, facetHolder);
         } else {
-            final Class<?> substitutedClass = classSubstitutor.getClass(cls);
+            final Class<?> substitutedClass = classSubstitutorRegistry.getClass(cls);
             facet = substitutedClass != null
                         ? new ObjectSpecIdFacetDerivedFromClassName(substitutedClass.getCanonicalName(), facetHolder)
                         : null;


[isis] 07/11: ISIS-2250: renames class is all

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 596b90a8bcf17cee0a4d11bfadb3b3b6b199ce0b
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Jan 9 16:01:26 2020 +0000

    ISIS-2250: renames class is all
---
 .../services/classsubstitutor/ClassSubstitutorForCollections.java       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
index be9b7d2..e308b73 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
@@ -36,7 +36,7 @@ import org.apache.isis.metamodel.spec.FreeStandingList;
 import lombok.NonNull;
 
 @Component
-@Named("isisMetaModel.ClassSubstitutorUnmodifiableCollections")
+@Named("isisMetaModel.ClassSubstitutorForCollections")
 @Order(OrderPrecedence.MIDPOINT + 1)
 public class ClassSubstitutorForCollections implements ClassSubstitutor {
 


[isis] 01/11: ISIS-2250: refactors SpecificationLoaderDefault

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 4ae7a3d621b1867fb249302f9d77f389866b3380
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Jan 9 11:44:27 2020 +0000

    ISIS-2250: refactors SpecificationLoaderDefault
    
    use constructor injection where possible.
---
 .../specloader/SpecificationLoaderDefault.java     | 83 +++++++++++++---------
 .../metamodel/MetaModelContext_forTesting.java     |  3 +-
 2 files changed, 50 insertions(+), 36 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java
index 59b5b38..59f3d68 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java
@@ -35,7 +35,6 @@ import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
-import org.apache.isis.applib.services.inject.ServiceInjector;
 import org.apache.isis.applib.services.registry.ServiceRegistry;
 import org.apache.isis.applib.util.schema.CommonDtoUtils;
 import org.apache.isis.commons.internal.base._Blackhole;
@@ -96,18 +95,19 @@ import lombok.extern.log4j.Log4j2;
 @Log4j2
 public class SpecificationLoaderDefault implements SpecificationLoader {
 
-    @Inject private ProgrammingModelService programmingModelService;
-    @Inject private IsisConfiguration isisConfiguration;
-    @Inject private IsisSystemEnvironment isisSystemEnvironment;
-    @Inject private ServiceRegistry serviceRegistry;
-    @Inject private IsisBeanTypeRegistryHolder isisBeanTypeRegistryHolder;
-    @Inject private ClassSubstitutor classSubstitutor = new ClassSubstitutorDefault();  // default for testing purposes only, overwritten in prod
+    private final IsisConfiguration isisConfiguration;
+    private final IsisSystemEnvironment isisSystemEnvironment;
+    private final ServiceRegistry serviceRegistry;
+    private final IsisBeanTypeRegistryHolder isisBeanTypeRegistryHolder;
+    private final ClassSubstitutor classSubstitutor = new ClassSubstitutorDefault();
+
+    private final ProgrammingModel programmingModel;
+    private final PostProcessor postProcessor;
 
-    private ProgrammingModel programmingModel;
-    private FacetProcessor facetProcessor;
-    private PostProcessor postProcessor;
     @Getter private MetaModelContext metaModelContext; // cannot inject, would cause circular dependency
-    
+
+    private FacetProcessor facetProcessor;
+
     private final SpecificationCacheDefault<ObjectSpecification> cache = 
             new SpecificationCacheDefault<>();
 
@@ -117,30 +117,48 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
     @Getter
     private boolean metamodelFullyIntrospected = false;
 
+    @Inject
+    public SpecificationLoaderDefault(
+            final ProgrammingModelService programmingModelService,
+            final IsisConfiguration isisConfiguration,
+            final IsisSystemEnvironment isisSystemEnvironment,
+            final ServiceRegistry serviceRegistry,
+            final IsisBeanTypeRegistryHolder isisBeanTypeRegistryHolder) {
+        this(
+                programmingModelService.getProgrammingModel(),
+                isisConfiguration,
+                isisSystemEnvironment,
+                serviceRegistry,
+                isisBeanTypeRegistryHolder);
+    }
+
+    SpecificationLoaderDefault(
+            final ProgrammingModel programmingModel,
+            final IsisConfiguration isisConfiguration,
+            final IsisSystemEnvironment isisSystemEnvironment,
+            final ServiceRegistry serviceRegistry,
+            final IsisBeanTypeRegistryHolder isisBeanTypeRegistryHolder) {
+        this.programmingModel = programmingModel;
+        this.postProcessor = new PostProcessor(programmingModel);
+        this.isisConfiguration = isisConfiguration;
+        this.isisSystemEnvironment = isisSystemEnvironment;
+        this.serviceRegistry = serviceRegistry;
+        this.isisBeanTypeRegistryHolder = isisBeanTypeRegistryHolder;
+    }
+
     /** JUnit Test Support */
-    public static SpecificationLoaderDefault getInstance (
-            IsisConfiguration isisConfiguration,
-            IsisSystemEnvironment isisSystemEnvironment,
-            ServiceRegistry serviceRegistry,
-            ServiceInjector serviceInjector,
-            ProgrammingModel programmingModel,
-            IsisBeanTypeRegistryHolder isisBeanTypeRegistryHolder) {
+    public static SpecificationLoaderDefault getInstance(
+            final IsisConfiguration isisConfiguration,
+            final IsisSystemEnvironment isisSystemEnvironment,
+            final ServiceRegistry serviceRegistry,
+            final ProgrammingModel programmingModel,
+            final IsisBeanTypeRegistryHolder isisBeanTypeRegistryHolder) {
 
-        val instance = new SpecificationLoaderDefault(); 
+        val instance = new SpecificationLoaderDefault(programmingModel, isisConfiguration, isisSystemEnvironment, serviceRegistry, isisBeanTypeRegistryHolder);
 
         instance.metaModelContext = serviceRegistry.lookupServiceElseFail(MetaModelContext.class);
-        
-        instance.isisConfiguration = isisConfiguration;
-        instance.isisSystemEnvironment = isisSystemEnvironment;
-        instance.serviceRegistry = serviceRegistry;
-        instance.programmingModel = programmingModel;
-
         instance.facetProcessor = new FacetProcessor(programmingModel, instance.metaModelContext);
-        instance.postProcessor = new PostProcessor(programmingModel);
-        
-        instance.isisBeanTypeRegistryHolder = isisBeanTypeRegistryHolder;
-        
-        
+
         return instance;
     }
 
@@ -152,9 +170,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
             log.debug("initialising {}", this);
         }
         this.metaModelContext = serviceRegistry.lookupServiceElseFail(MetaModelContext.class);
-        this.programmingModel = programmingModelService.getProgrammingModel();
         this.facetProcessor = new FacetProcessor(programmingModel, metaModelContext);
-        this.postProcessor = new PostProcessor(programmingModel);
     }
     
     /**
@@ -276,7 +292,6 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
         disposeMetaModel();
         facetProcessor.shutdown();
         postProcessor.shutdown();
-        postProcessor = null;
         facetProcessor = null;
     }
 
@@ -300,7 +315,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
     public boolean loadSpecifications(Class<?>... domainTypes) {
         // ensure that all types are loadable
         if (Arrays.stream(domainTypes)
-                .map(domainType -> classSubstitutor.getClass(domainType))
+                .map(classSubstitutor::getClass)
                 .anyMatch(Objects::isNull)) {
             return false;
         }
diff --git a/core/metamodel/src/test/java/org/apache/isis/metamodel/MetaModelContext_forTesting.java b/core/metamodel/src/test/java/org/apache/isis/metamodel/MetaModelContext_forTesting.java
index 709eb69..c464e20 100644
--- a/core/metamodel/src/test/java/org/apache/isis/metamodel/MetaModelContext_forTesting.java
+++ b/core/metamodel/src/test/java/org/apache/isis/metamodel/MetaModelContext_forTesting.java
@@ -236,8 +236,7 @@ public final class MetaModelContext_forTesting implements MetaModelContext {
             specificationLoader = SpecificationLoaderDefault.getInstance(
                     configuration, 
                     environment, 
-                    serviceRegistry, 
-                    serviceInjector, 
+                    serviceRegistry,
                     programmingModel,
                     isisBeanTypeRegistryHolder);
             


[isis] 06/11: ISIS-2250: and special case for Vector also (legacy collection class).

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit d17d15dc8680685b90b8351969073974eb6b2ce4
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Jan 9 15:58:11 2020 +0000

    ISIS-2250: and special case for Vector also (legacy collection class).
---
 .../classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java      | 5 +++--
 .../services/classsubstitutor/ClassSubstitutorForCollections.java    | 5 +++++
 .../ObjectSpecIdFacetDerivedFromClassNameFactoryTest.java            | 2 +-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
index 9807ab2..03efdc8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
@@ -50,13 +50,14 @@ extends FacetFactoryAbstract
 implements MetaModelRefiner, ObjectSpecIdFacetFactory {
 
     @Inject
-    private ClassSubstitutorRegistry classSubstitutorRegistry;
+    private ClassSubstitutorRegistry classSubstitutorRegistry =
+            // default for testing purposes only, overwritten in prod
+            new ClassSubstitutorRegistry(Collections.singletonList( new ClassSubstitutorDefault()));
 
 
     public ObjectSpecIdFacetDerivedFromClassNameFactory() {
         super(FeatureType.OBJECTS_ONLY);
     }
-    // default for testing purposes only, overwritten in prod
     public ObjectSpecIdFacetDerivedFromClassNameFactory(ClassSubstitutorRegistry classSubstitutorRegistry) {
         this();
         this.classSubstitutorRegistry = classSubstitutorRegistry;
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
index 209041e..be9b7d2 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 import java.util.SortedSet;
+import java.util.Vector;
 
 import javax.inject.Named;
 
@@ -44,6 +45,10 @@ public class ClassSubstitutorForCollections implements ClassSubstitutor {
         if(FreeStandingList.class.isAssignableFrom(cls)) {
             return FreeStandingList.class;
         }
+        // legacy
+        if(Vector.class.isAssignableFrom(cls)) {
+            return Vector.class;
+        }
         if(List.class.isAssignableFrom(cls)) {
             return List.class;
         }
diff --git a/core/metamodel/src/test/java/org/apache/isis/metamodel/facets/object/objectspecid/ObjectSpecIdFacetDerivedFromClassNameFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/metamodel/facets/object/objectspecid/ObjectSpecIdFacetDerivedFromClassNameFactoryTest.java
index 3a9c54d..aece70e 100644
--- a/core/metamodel/src/test/java/org/apache/isis/metamodel/facets/object/objectspecid/ObjectSpecIdFacetDerivedFromClassNameFactoryTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/metamodel/facets/object/objectspecid/ObjectSpecIdFacetDerivedFromClassNameFactoryTest.java
@@ -44,7 +44,7 @@ public class ObjectSpecIdFacetDerivedFromClassNameFactoryTest extends AbstractFa
 
     @Before
     public void setUp() throws Exception {
-        facetFactory = new ObjectSpecIdFacetDerivedFromClassNameFactory(new ClassSubstitutorRegistry(Collections.singletonList( new ClassSubstitutorDefault())));
+        facetFactory = new ObjectSpecIdFacetDerivedFromClassNameFactory();
     }
 
     public static class Customer {


[isis] 08/11: ISIS-2250: debugs and fixes spec loader blocking issue.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 27c56a586ab98d01779ba895be09a8420fb8e538
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Jan 9 17:01:01 2020 +0000

    ISIS-2250: debugs and fixes spec loader blocking issue.
---
 .../org/apache/isis/config/IsisConfiguration.java  |  7 +-
 .../MethodPrefixBasedFacetFactoryAbstract.java     | 94 +++++++++++++---------
 .../specloader/SpecificationLoaderDefault.java     | 23 +++++-
 .../specimpl/ObjectSpecificationAbstract.java      |  2 -
 .../validator/MetaModelValidatorAbstract.java      |  7 +-
 .../validator/MetaModelValidatorVisiting.java      | 16 ++--
 6 files changed, 93 insertions(+), 56 deletions(-)

diff --git a/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java b/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java
index f677e81..36be8c3 100644
--- a/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java
+++ b/core/config/src/main/java/org/apache/isis/config/IsisConfiguration.java
@@ -503,7 +503,7 @@ public class IsisConfiguration {
         @Data
         public static class Introspector {
             /**
-             * Whether to perform introspection and metamodel validation in parallel.
+             * Whether to perform introspection in parallel.
              */
             private boolean parallelize = true;
             /**
@@ -554,6 +554,11 @@ public class IsisConfiguration {
         @Data
         public static class Validator {
 
+            /**
+             * Whether to perform metamodel validation in parallel.
+             */
+            private boolean parallelize = true;
+
             private boolean allowDeprecated = true;
             private boolean ensureUniqueObjectTypes = true;
             private boolean checkModuleExtent = true;
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/MethodPrefixBasedFacetFactoryAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/MethodPrefixBasedFacetFactoryAbstract.java
index 26a2bf9..72d87ec 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/MethodPrefixBasedFacetFactoryAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/MethodPrefixBasedFacetFactoryAbstract.java
@@ -19,11 +19,16 @@
 package org.apache.isis.metamodel.facets;
 
 import java.util.EnumSet;
+import java.util.function.Consumer;
 
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.facetapi.FeatureType;
 import org.apache.isis.metamodel.progmodel.ProgrammingModel;
+import org.apache.isis.metamodel.spec.ObjectSpecification;
 import org.apache.isis.metamodel.spec.feature.Contributed;
+import org.apache.isis.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.metamodel.specloader.validator.MetaModelValidator;
+import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorVisiting;
 
 import lombok.Getter;
 import lombok.NonNull;
@@ -63,47 +68,56 @@ implements MethodPrefixBasedFacetFactory {
         
         val noParamsOnly = getConfiguration().getReflector().getValidator().isNoParamsOnly();
 
-        programmingModel.addValidator((objectSpec, metaModelValidator) -> {
-            
-            // ensure accepted actions do not have any of the reserved prefixes
-            objectSpec.streamObjectActions(Contributed.EXCLUDED)
-            .forEach(objectAction->{
-                
-                val actionId = objectAction.getId();
-                
-                for (val prefix : prefixes) {
-                    
-                    if (isPrefixed(actionId, prefix)) {
-
-                        val explanation =
-                                objectAction.getParameterCount() > 0 
-                                && noParamsOnly 
-                                && (MethodLiteralConstants.HIDE_PREFIX.equals(prefix) 
-                                        || MethodLiteralConstants.DISABLE_PREFIX.equals(prefix))
-                                ? " (such methods must have no parameters, '"
-                                    + "isis.reflector.validator.no-params-only"
-                                    + "' config property)"
-                                        : "";
-
-                        val message = "%s#%s: has prefix %s, is probably intended as a supporting method "
-                                + "for a property, collection or action%s.  If the method is intended to "
-                                + "be an action, then rename and use @ActionLayout(named=\"...\") or ignore "
-                                + "completely using @Programmatic";
-                        
-                        metaModelValidator.onFailure(
-                                objectSpec,
-                                objectSpec.getIdentifier(),
-                                message,
-                                objectSpec.getIdentifier().getClassName(),
-                                actionId,
-                                prefix,
-                                explanation);
-                    }
-                }
-            });
-
-            return true;
+        programmingModel.addValidator(new MetaModelValidatorVisiting.Visitor() {
 
+            @Override
+            public String toString() {
+                return "MetaModelValidatorVisiting.Visitor : MethodPrefixBasedFacetFactoryAbstract : " + prefixes.toList().toString();
+            }
+
+            @Override
+            public boolean visit(ObjectSpecification objectSpec, MetaModelValidator metaModelValidator) {
+
+                // ensure accepted actions do not have any of the reserved prefixes
+                objectSpec.streamObjectActions(Contributed.EXCLUDED)
+                        .forEach(objectAction -> {
+
+                            val actionId = objectAction.getId();
+
+                            for (val prefix : prefixes) {
+
+                                if (isPrefixed(actionId, prefix)) {
+
+                                    val explanation =
+                                            objectAction.getParameterCount() > 0
+                                                    && noParamsOnly
+                                                    && (MethodLiteralConstants.HIDE_PREFIX.equals(prefix)
+                                                    || MethodLiteralConstants.DISABLE_PREFIX.equals(prefix))
+                                                    ? " (such methods must have no parameters, '"
+                                                    + "isis.reflector.validator.no-params-only"
+                                                    + "' config property)"
+                                                    : "";
+
+                                    val message = "%s#%s: has prefix %s, is probably intended as a supporting method "
+                                            + "for a property, collection or action%s.  If the method is intended to "
+                                            + "be an action, then rename and use @ActionLayout(named=\"...\") or ignore "
+                                            + "completely using @Programmatic";
+
+                                    metaModelValidator.onFailure(
+                                            objectSpec,
+                                            objectSpec.getIdentifier(),
+                                            message,
+                                            objectSpec.getIdentifier().getClassName(),
+                                            actionId,
+                                            prefix,
+                                            explanation);
+                                }
+                            }
+                        });
+
+                return true;
+
+            }
         });
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java
index d45eb44..9559a1d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/SpecificationLoaderDefault.java
@@ -73,6 +73,7 @@ import org.apache.isis.metamodel.valuetypes.ValueTypeRegistry;
 import static org.apache.isis.commons.internal.base._With.requires;
 
 import lombok.Getter;
+import lombok.Setter;
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
@@ -118,7 +119,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
     /**
      * We only ever mark the metamodel as fully introspected if in {@link #isFullIntrospect() full} introspection mode.
      */
-    @Getter
+    @Getter @Setter
     private boolean metamodelFullyIntrospected = false;
 
     @Inject
@@ -275,7 +276,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
         log.info("Metamodel created in " + (long)stopWatch.getMillis() + " ms.");
 
         if(isFullIntrospect()) {
-            metamodelFullyIntrospected = true;
+            setMetamodelFullyIntrospected(true);
         }
     }
     
@@ -291,7 +292,18 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
         val failures = new ValidationFailures();
         programmingModel.streamValidators()
         .map(MetaModelValidatorAbstract.class::cast)
-        .forEach(validator->validator.collectFailuresInto(failures));
+        .forEach(validator -> {
+            log.debug("Running validator: {}", validator);
+            try {
+                validator.collectFailuresInto(failures);
+            } catch (Throwable t) {
+                log.error(t);
+                throw t;
+            } finally {
+                log.debug("Done validator: {}", validator);
+            }
+        });
+        log.debug("Done");
         return failures;
     }
 
@@ -370,6 +382,9 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
     }
 
     public void revalidateIfNecessary() {
+        if(!isMetamodelFullyIntrospected()) {
+            return;
+        }
         if(!this.isisConfiguration.getReflector().getIntrospector().isValidateIncrementally()) {
             return;
         }
@@ -393,7 +408,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
     
     @Override
     public void forEach(Consumer<ObjectSpecification> onSpec) {
-        val shouldRunConcurrent = isisConfiguration.getReflector().getIntrospector().isParallelize();
+        val shouldRunConcurrent = isisConfiguration.getReflector().getValidator().isParallelize();
         val vList = cache.getVList(); // vList is thread-safe
         if(shouldRunConcurrent) {
             vList.forEachParallel(onSpec);    
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
index bad3057..122cde4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
@@ -326,11 +326,9 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
         return this.introspectionState.compareTo(upTo) < 0;
     }
     
-    
     protected abstract void introspectTypeHierarchy();
     protected abstract void introspectMembers();
 
-
     protected void loadSpecOfSuperclass(final Class<?> superclass) {
         if (superclass == null) {
             return;
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorAbstract.java
index f796b74..4605212 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorAbstract.java
@@ -60,5 +60,10 @@ implements MetaModelValidator, MetaModelContextAware {
     protected IsisConfiguration getConfiguration() {
         return metaModelContext.getConfiguration();
     }
-    
+
+    @Override
+    public String toString() {
+        return getClass().getName();
+    }
+
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorVisiting.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorVisiting.java
index 2494719..082441a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorVisiting.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorVisiting.java
@@ -29,6 +29,13 @@ import lombok.val;
 
 public class MetaModelValidatorVisiting extends MetaModelValidatorAbstract {
 
+    @Override
+    public String toString() {
+        return "MetaModelValidatorVisiting{" +
+                "visitor=" + visitor +
+                '}';
+    }
+
     // -- INTERFACES
     
     @FunctionalInterface
@@ -87,18 +94,11 @@ public class MetaModelValidatorVisiting extends MetaModelValidatorAbstract {
         val specLoader = (SpecificationLoaderDefault)super.getMetaModelContext().getSpecificationLoader();
         
         specLoader.forEach(spec->{
-
             if(! includeIf.test(spec)) {
                 return;
             }
-            
-            visitor.visit(spec, this);            
+            visitor.visit(spec, this);
         });
-        
-    }
-
-    private static boolean filter(ObjectSpecification spec) {
-        return spec.isManagedBean() || spec.getBeanSort().isUnknown();
     }
 
     private void summarize() {