You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2019/10/06 14:59:31 UTC

[isis] branch v2 updated: ISIS-2158 major: refactoring ProgrammingModel

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

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


The following commit(s) were added to refs/heads/v2 by this push:
     new 150db59  ISIS-2158 major: refactoring ProgrammingModel
150db59 is described below

commit 150db5921b487c0faaa03d0a4a032c25d17b4ca0
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sun Oct 6 16:59:20 2019 +0200

    ISIS-2158 major: refactoring ProgrammingModel
    
    - provides an API to handle facet processing order via enum
    ProcessingOrder
    - provides an API to add multiple markers to facet- factories during
    their registration with the ProgrammingModel instance
    - after registration phase the ProgrammingModel instance is initialized
    with an optional facet-factory filter, this allows to filter by markers
    eg. Marker.DEPRECATED or Marker.INCUBATING
    - removing the obsolete ProgrammingModelPlugin interface
---
 .../isis/applib/annotation/ActionLayout.java       |   2 +-
 .../apache/isis/applib/annotation/Collection.java  |   2 +-
 .../isis/applib/annotation/CollectionLayout.java   |   2 +-
 .../apache/isis/applib/annotation/Property.java    |   2 +-
 .../isis/applib/annotation/PropertyLayout.java     |   2 +-
 .../commons/internal/collections/_Multimaps.java   |  17 +
 .../facets/object/mixin/MixinIntendedAs.java       |  18 +-
 .../facets/param/name/ParameterNameFacetTest.java  |  15 +-
 .../isis/metamodel/progmodel/FacetFactorySet.java  |  20 +-
 .../isis/metamodel/progmodel/ProgrammingModel.java | 124 +++++++-
 .../progmodel/ProgrammingModelAbstract.java        | 171 ++++-------
 ...ct.java => ProgrammingModelAbstractLegacy.java} |  17 +-
 .../progmodel/ProgrammingModelPlugin.java          |  80 +----
 .../progmodel/ProgrammingModelService.java         |   4 +
 .../dflt/ProgrammingModelFacetsJava8.java          | 342 ++++++++-------------
 .../MetaModelValidatorServiceDefault.java          |  16 +-
 .../specloader/ProgrammingModelServiceDefault.java |  62 +++-
 .../metamodel/specloader/ReflectorConstants.java   |  14 +-
 .../specloader/SpecificationLoaderDefault.java     |  17 +-
 .../specloader/facetprocessor/FacetProcessor.java  |   4 +-
 .../SpecificationLoaderTestAbstract.java           |  43 ++-
 .../jdo/metamodel/JdoProgrammingModelPlugin.java   |  53 ++++
 ...cIdFacetForJdoPersistenceCapableAnnotation.java |   2 +-
 .../PersistenceSessionFactoryMetamodelRefiner.java |  27 +-
 .../org/apache/isis/jdo/IsisBootDataNucleus.java   |   2 +
 .../jdo/datanucleus/JDOStateManagerForIsis.java    |   2 +-
 .../mixins/Persistable_datanucleusIdLong.java      |   3 +-
 .../mixins/Persistable_datanucleusVersionLong.java |   3 +-
 .../Persistable_datanucleusVersionTimestamp.java   |   3 +-
 .../mixins/Persistable_downloadJdoMetadata.java    |   3 +-
 .../bootstrapping/builtin-singleton.list           |   1 -
 ...orPlugin.java => IncubatorMetaModelPlugin.java} |  24 +-
 .../extensions/incubator/IsisBootIncubator.java    |  14 +-
 ...isis.metamodel.progmodel.ProgrammingModelPlugin |   1 -
 .../apache/isis/extensions/sse/IsisBootSse.java    |   1 +
 .../{SsePlugin.java => SseMetaModelPlugin.java}    |  23 +-
 ...isis.metamodel.progmodel.ProgrammingModelPlugin |   1 -
 37 files changed, 611 insertions(+), 526 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionLayout.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionLayout.java
index 13925aa..09776a9 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionLayout.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionLayout.java
@@ -31,7 +31,7 @@ import javax.xml.bind.annotation.XmlType;
  * Layout hints for actions.
  */
 @Inherited
-@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
+@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
 @Retention(RetentionPolicy.RUNTIME)
 public @interface ActionLayout {
 
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/Collection.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/Collection.java
index 42ad362..76a0d68 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/Collection.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/Collection.java
@@ -33,7 +33,7 @@ import org.apache.isis.applib.events.domain.CollectionDomainEvent;
  * Domain semantics for domain object collection.
  */
 @Inherited
-@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
+@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Collection {
 
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/CollectionLayout.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/CollectionLayout.java
index fcfa6f1..6dff9c8 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/CollectionLayout.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/CollectionLayout.java
@@ -30,7 +30,7 @@ import java.util.Comparator;
  * Layout hints for collections.
  */
 @Inherited
-@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })
+@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
 @Retention(RetentionPolicy.RUNTIME)
 public @interface CollectionLayout {
 
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java
index 1ca48a5..5f06833 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java
@@ -41,7 +41,7 @@ import org.apache.isis.applib.value.Clob;
  * Domain semantics for domain object property.
  */
 @Inherited
-@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })
+@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Property {
 
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PropertyLayout.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PropertyLayout.java
index 6db4cc3..fce99b6 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/PropertyLayout.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PropertyLayout.java
@@ -31,7 +31,7 @@ import java.lang.annotation.Target;
  * @see org.apache.isis.applib.annotation.ParameterLayout
  */
 @Inherited
-@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })
+@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
 @Retention(RetentionPolicy.RUNTIME)
 public @interface PropertyLayout {
 
diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/collections/_Multimaps.java b/core/commons/src/main/java/org/apache/isis/commons/internal/collections/_Multimaps.java
index 475f9e2..b6eab50 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/collections/_Multimaps.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/collections/_Multimaps.java
@@ -292,6 +292,23 @@ public class _Multimaps {
         };
     }
 
+    // -- SHORTCUTS
+    
+    /**
+     * @return HashMap of Lists with given listFactory
+     */
+    public static <K, V> ListMultimap<K, V> newListMultimap(Supplier<List<V>> listFactory){
+        return newListMultimap(HashMap<K, List<V>>::new, listFactory);
+    }
+    
+    /**
+     * 
+     * @return HashMap of Sets with given setFactory
+     */
+    public static <K, V> SetMultimap<K, V> newSetMultimap(Supplier<Set<V>> setFactory){
+        return newSetMultimap(HashMap<K, Set<V>>::new, setFactory);
+    }
+    
     // -- CONVENIENT DEFAULTS
 
     /**
diff --git a/core/detached-tests/src/test/java/org/apache/isis/metamodel/facets/object/mixin/MixinIntendedAs.java b/core/detached-tests/src/test/java/org/apache/isis/metamodel/facets/object/mixin/MixinIntendedAs.java
index 4ee2062..292a7a4 100644
--- a/core/detached-tests/src/test/java/org/apache/isis/metamodel/facets/object/mixin/MixinIntendedAs.java
+++ b/core/detached-tests/src/test/java/org/apache/isis/metamodel/facets/object/mixin/MixinIntendedAs.java
@@ -22,6 +22,7 @@ import java.lang.reflect.Method;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.commons.internal.environment.IsisSystemEnvironment;
+import org.apache.isis.commons.internal.functions._Predicates;
 import org.apache.isis.config.IsisConfiguration;
 import org.apache.isis.metamodel.MetaModelContext;
 import org.apache.isis.metamodel.facetapi.FacetHolder;
@@ -32,9 +33,9 @@ import org.apache.isis.metamodel.facets.FacetFactory;
 import org.apache.isis.metamodel.facets.FacetedMethodParameter;
 import org.apache.isis.metamodel.facets.MethodRemoverConstants;
 import org.apache.isis.metamodel.metamodelvalidator.dflt.MetaModelValidatorDefault;
-import org.apache.isis.metamodel.progmodel.ProgrammingModelAbstract;
 import org.apache.isis.metamodel.progmodels.dflt.ProgrammingModelFacetsJava8;
 import org.apache.isis.metamodel.specloader.SpecificationLoaderDefault;
+import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorComposite;
 
 import lombok.val;
 
@@ -44,9 +45,9 @@ abstract class MixinIntendedAs {
 
     protected void setUp() throws Exception {
 
-        programmingModel = new ProgrammingModelFacetsJava8(
-                ProgrammingModelAbstract.DeprecatedPolicy.IGNORE);
-        programmingModel.init();
+        val mmValidator = MetaModelValidatorComposite.asComposite(new MetaModelValidatorDefault()); 
+        
+        programmingModel = new ProgrammingModelFacetsJava8();
         
         // PRODUCTION
 
@@ -54,12 +55,13 @@ abstract class MixinIntendedAs {
                 .specificationLoader(SpecificationLoaderDefault.getInstance(
                         new IsisConfiguration(),
                         new IsisSystemEnvironment(),
-                        new ProgrammingModelFacetsJava8(ProgrammingModelAbstract.DeprecatedPolicy.HONOUR),
-                        new MetaModelValidatorDefault()))
+                        programmingModel,
+                        mmValidator))
 //                .serviceInjector(mockServiceInjector)
 //                .serviceRegistry(mockServiceRegistry)
                 .build());
         
+        programmingModel.init(_Predicates.alwaysTrue(), mmValidator);
         MetaModelContext.current().getSpecificationLoader().init();
         
     }
@@ -87,7 +89,7 @@ abstract class MixinIntendedAs {
                         MethodRemoverConstants.NOOP, 
                         facetHolder);
         
-        programmingModel.getList().stream()
+        programmingModel.stream()
 //        .filter(facetFactory->!facetFactory.getClass().getSimpleName().startsWith("Grid"))
 //        .peek(facetFactory->System.out.println("### " + facetFactory.getClass().getName()))
         .forEach(facetFactory->facetFactory.process(processClassContext));
@@ -114,7 +116,7 @@ abstract class MixinIntendedAs {
                         MethodRemoverConstants.NOOP, 
                         facetedMethodParameter);
         
-        programmingModel.getList()
+        programmingModel.stream()
         .forEach(facetFactory->facetFactory.processParams(processParameterContext));
         
         return facetedMethodParameter;
diff --git a/core/detached-tests/src/test/java/org/apache/isis/metamodel/facets/param/name/ParameterNameFacetTest.java b/core/detached-tests/src/test/java/org/apache/isis/metamodel/facets/param/name/ParameterNameFacetTest.java
index 5e54ea6..2ccbf03 100644
--- a/core/detached-tests/src/test/java/org/apache/isis/metamodel/facets/param/name/ParameterNameFacetTest.java
+++ b/core/detached-tests/src/test/java/org/apache/isis/metamodel/facets/param/name/ParameterNameFacetTest.java
@@ -27,10 +27,15 @@ import org.junit.Before;
 import org.junit.Test;
 
 import org.apache.isis.applib.annotation.ParameterLayout;
+import org.apache.isis.commons.internal.functions._Predicates;
 import org.apache.isis.metamodel.facets.AbstractFacetFactoryJUnit4TestCase;
 import org.apache.isis.metamodel.facets.FacetFactory;
 import org.apache.isis.metamodel.facets.all.named.NamedFacet;
+import org.apache.isis.metamodel.metamodelvalidator.dflt.MetaModelValidatorDefault;
 import org.apache.isis.metamodel.progmodels.dflt.ProgrammingModelFacetsJava8;
+import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorComposite;
+
+import lombok.val;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
@@ -45,8 +50,9 @@ public class ParameterNameFacetTest extends AbstractFacetFactoryJUnit4TestCase {
 
     @Before
     public void setUp() throws Exception {
-        programmingModel = new ProgrammingModelFacetsJava8(ProgrammingModelAbstract.DeprecatedPolicy.IGNORE);
-        programmingModel.init();
+        val mmValidator = MetaModelValidatorComposite.asComposite(new MetaModelValidatorDefault());
+        programmingModel = new ProgrammingModelFacetsJava8();
+        programmingModel.init(_Predicates.alwaysTrue(), mmValidator);
         super.setUpFacetedMethodAndParameter();
     }
 
@@ -72,7 +78,8 @@ public class ParameterNameFacetTest extends AbstractFacetFactoryJUnit4TestCase {
         final FacetFactory.ProcessParameterContext processParameterContext = 
                 new FacetFactory.ProcessParameterContext(
                         Customer.class, actionMethod, 0, null, facetedMethodParameter);
-        programmingModel.getList().forEach(facetFactory->facetFactory.processParams(processParameterContext));
+        programmingModel.stream()
+        .forEach(facetFactory->facetFactory.processParams(processParameterContext));
 
         // then
         final NamedFacet namedFacet = facetedMethodParameter.getFacet(NamedFacet.class);
@@ -101,7 +108,7 @@ public class ParameterNameFacetTest extends AbstractFacetFactoryJUnit4TestCase {
         final FacetFactory.ProcessParameterContext processParameterContext = 
                 new FacetFactory.ProcessParameterContext(
                         Customer.class, actionMethod, 0, null, facetedMethodParameter);
-        programmingModel.getList().forEach(facetFactory->facetFactory.processParams(processParameterContext));
+        programmingModel.stream().forEach(facetFactory->facetFactory.processParams(processParameterContext));
 
         // then
         final NamedFacet namedFacet = facetedMethodParameter.getFacet(NamedFacet.class);
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/FacetFactorySet.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/FacetFactorySet.java
index b104cfe..25d53b6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/FacetFactorySet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/FacetFactorySet.java
@@ -22,12 +22,12 @@ package org.apache.isis.metamodel.progmodel;
 import java.util.List;
 
 import org.apache.isis.commons.internal.factory.InstanceUtil;
-import org.apache.isis.config.ConfigurationConstants;
 import org.apache.isis.config.IsisConfigurationLegacy;
 import org.apache.isis.metamodel.facets.FacetFactory;
 import org.apache.isis.metamodel.specloader.ReflectorConstants;
 
-public interface FacetFactorySet {
+@Deprecated
+interface FacetFactorySet {
 
     List<FacetFactory> getList();
 
@@ -42,22 +42,6 @@ public interface FacetFactorySet {
     void removeFactory(Class<? extends FacetFactory> facetFactoryClass);
 
     /**
-     * Key used to lookup comma-separated list of {@link FacetFactory}s to
-     * include.
-     *
-     * @see #FACET_FACTORY_EXCLUDE_CLASS_NAME_LIST
-     */
-    String FACET_FACTORY_INCLUDE_CLASS_NAME_LIST = ConfigurationConstants.ROOT + "reflector.facets.include";
-
-    /**
-     * Key used to lookup comma-separated list of {@link FacetFactory}s to
-     * exclude.
-     *
-     * @see #FACET_FACTORY_INCLUDE_CLASS_NAME_LIST
-     */
-    String FACET_FACTORY_EXCLUDE_CLASS_NAME_LIST = ConfigurationConstants.ROOT + "reflector.facets.exclude";
-
-    /**
      * This is a bit nasty, but currently the bootstrapping of the metamodel for integration tests vs the webapp differs;
      * the intent of this class is to centralize some logic that should be applied in both cases.
      */
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModel.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModel.java
index eb5c5b6..baac223 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModel.java
@@ -19,10 +19,128 @@
 
 package org.apache.isis.metamodel.progmodel;
 
-import org.apache.isis.metamodel.facetapi.MetaModelValidatorRefiner;
+import static org.apache.isis.commons.internal.base._NullSafe.isEmpty;
 
-public interface ProgrammingModel extends FacetFactorySet, PostProcessorSet, MetaModelValidatorRefiner {
+import java.util.EnumSet;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
 
-    void init();
+import javax.annotation.Nullable;
 
+import org.apache.isis.commons.internal.base._Casts;
+import org.apache.isis.commons.internal.functions._Functions;
+import org.apache.isis.commons.internal.functions._Predicates;
+import org.apache.isis.metamodel.facets.FacetFactory;
+import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorComposite;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.Value;
+import lombok.val;
+
+public interface ProgrammingModel 
+extends /*FacetFactorySet,*/ PostProcessorSet /*, MetaModelValidatorRefiner*/ {
+
+    // -- TYPES
+    
+    /**
+     * 
+     * @apiNote Prefixes are without any semantic meaning, just to make the ordering 
+     * transparent to the human reader. 
+     * Order is defined by {@link ProcessingOrder#ordinal()}
+     *
+     */
+    static enum ProcessingOrder {
+        
+        A1_FALLBACK_DEFAULTS,
+        A2_AFTER_FALLBACK_DEFAULTS,
+        
+        B1_OBJECT_NAMING,
+        B2_AFTER_OBJECT_NAMING,
+        
+        C1_METHOD_REMOVING,
+        C2_AFTER_METHOD_REMOVING,
+        
+        D1_MANDATORY_SUPPORT,
+        D2_AFTER_MANDATORY_SUPPORT,
+        
+        E1_MEMBER_MODELLING,
+        E2_AFTER_MEMBER_MODELLING,
+        
+        F1_LAYOUT,
+        F2_AFTER_LAYOUT,
+        
+        G1_VALUE_TYPES, 
+        G2_AFTER_VALUE_TYPES,
+        
+        Z0_BEFORE_FINALLY,
+        Z1_FINALLY, 
+        Z2_AFTER_FINALLY,
+    }
+    
+    static enum Marker {
+        DEPRECATED, 
+        INCUBATING,
+    }
+    
+    @Value(staticConstructor = "of") @EqualsAndHashCode(of = "type")
+    static final class FactoryEntry<T extends FacetFactory> {
+        @NonNull Class<T> type;
+        @NonNull Supplier<? extends T> supplier; 
+        Marker[] markers;
+        @Getter(lazy = true) final T factoryInstance = supplier.get();
+    }
+    
+    // -- INTERFACE
+    
+    <T extends FacetFactory> void add(
+            ProcessingOrder order, 
+            Class<T> type, 
+            Supplier<? extends T> supplier, 
+            Marker ... markers);
+    
+    /**
+     * Finalizes the factory collection, can not be modified afterwards.
+     * @param filter - the final programming model will only contain factories accepted by this filter
+     * @param metaModelValidator
+     */
+    void init(Predicate<FactoryEntry<?>> filter, MetaModelValidatorComposite metaModelValidator);
+    
+    Stream<FacetFactory> stream();
+    
+    // -- SHORTCUTS
+    
+    default <T extends FacetFactory> void add(
+            ProcessingOrder order, 
+            Class<T> type, 
+            Marker ... markers) {
+        
+        final Supplier<FacetFactory> supplier = _Functions.uncheckedSupplier(type::newInstance);
+        add(order, type, _Casts.uncheckedCast(supplier), markers);
+    }
+    
+    // -- PREDICATES
+    
+    public static Predicate<FactoryEntry<?>> excluding(@Nullable EnumSet<Marker> excludingMarkers) {
+        if(excludingMarkers==null) {
+            return _Predicates.alwaysTrue();
+        }
+        return factoryEntry -> {
+            val markersOnFactory = factoryEntry.getMarkers();
+            if(isEmpty(markersOnFactory)) {
+                return true; // accept
+            }
+            for(val markerOnFactory : markersOnFactory) {
+                if(excludingMarkers.contains(markerOnFactory)) {
+                    return true; // don't  accept
+                }
+            }
+            return true; // accept
+        };
+    }
+
+    
+    
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelAbstract.java
index 224dbde..7ccd5a0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelAbstract.java
@@ -20,136 +20,99 @@
 package org.apache.isis.metamodel.progmodel;
 
 import java.util.Collections;
-import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
 
 import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.commons.internal.factory.InstanceUtil;
+import org.apache.isis.commons.internal.collections._Multimaps;
+import org.apache.isis.commons.internal.collections._Multimaps.SetMultimap;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.metamodel.facetapi.MetaModelValidatorRefiner;
 import org.apache.isis.metamodel.facets.FacetFactory;
 import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorComposite;
 
-public abstract class ProgrammingModelAbstract implements ProgrammingModel {
-
-    private final List<FacetFactory> facetFactories = _Lists.newArrayList();
-    private final List<Object> facetFactoryInstancesOrClasses = _Lists.newLinkedList();
-
-    public enum DeprecatedPolicy {
-        IGNORE,
-        HONOUR;
-    }
+import lombok.Getter;
+import lombok.val;
 
-    protected final DeprecatedPolicy deprecatedPolicy;
-
-    public ProgrammingModelAbstract(
-            final DeprecatedPolicy deprecatedPolicy) {
+public abstract class ProgrammingModelAbstract implements ProgrammingModel {
 
-        this.deprecatedPolicy = deprecatedPolicy;
-    }
+    @Getter(onMethod = @__(@Override))
+    private final List<ObjectSpecificationPostProcessor> postProcessors = _Lists.newArrayList();
+    
+    private List<FacetFactory> unmodifiableFactories;
 
     @Override
-    public void init() {
-        initializeIfRequired();
+    public <T extends FacetFactory> void add(
+            ProcessingOrder order, 
+            Class<T> type, 
+            Supplier<? extends T> supplier, 
+            Marker ... markers) {
+        
+        assertNotInitialized();
+        
+        val factoryEntry = FactoryEntry.of(type, supplier, markers);
+        factoryEntriesByOrder.putElement(order, factoryEntry);
     }
 
-    private void initializeIfRequired() {
-        if(!facetFactories.isEmpty()) {
-            return;
+    @Override
+    public void init(
+            Predicate<FactoryEntry<?>> filter, 
+            MetaModelValidatorComposite metaModelValidator) {
+        
+        assertNotInitialized();
+        
+        for (val facetFactory : snapshot(filter)) {
+            if(facetFactory instanceof MetaModelValidatorRefiner) {
+                val metaModelValidatorRefiner = (MetaModelValidatorRefiner) facetFactory;
+                metaModelValidatorRefiner.refineMetaModelValidator(metaModelValidator);
+            }
         }
-        initialize();
+        
+        this.unmodifiableFactories = 
+                Collections.unmodifiableList(snapshot(filter));
     }
 
-    private void initialize() {
-        for (final Object factoryInstanceOrClass : facetFactoryInstancesOrClasses) {
-            final FacetFactory facetFactory = asFacetFactory(factoryInstanceOrClass);
-            facetFactories.add(facetFactory);
+    @Override
+    public Stream<FacetFactory> stream() {
+        if(unmodifiableFactories==null) {
+            return Stream.empty();
         }
+        return unmodifiableFactories.stream();
     }
+    
+    // -- HELPER
 
-    private static FacetFactory asFacetFactory(final Object factoryInstanceOrClass) {
-        if(factoryInstanceOrClass instanceof FacetFactory) {
-            return (FacetFactory) factoryInstanceOrClass;
-        } else {
-            @SuppressWarnings("unchecked") final
-            Class<? extends FacetFactory> factoryClass = (Class<? extends FacetFactory>) factoryInstanceOrClass;
-            return (FacetFactory) InstanceUtil.createInstance(factoryClass);
-        }
+    private boolean isInitialized() {
+        return unmodifiableFactories!=null;
     }
-
+    
     private void assertNotInitialized() {
-        if(!facetFactories.isEmpty()) {
-            throw new IllegalStateException("Programming model already initialized");
+        if(isInitialized()) {
+            throw _Exceptions.unrecoverable(
+                    "The programming-model was already initialized, it cannot be altered.");
         }
     }
-
-
-    @Override
-    public final List<FacetFactory> getList() {
-        initializeIfRequired();
-        return Collections.unmodifiableList(facetFactories);
-    }
-
-    @Override
-    public final void addFactory(final Class<? extends FacetFactory> factoryClass) {
-        addFactory(factoryClass, Position.END);
-    }
-
-    @Override
-    public final void addFactory(final Class<? extends FacetFactory> factoryClass, final Position position) {
-        addFactory((Object)factoryClass, position);
-    }
-
-    @Override
-    public void addFactory(final FacetFactory facetFactory) {
-        addFactory(facetFactory, Position.END);
-    }
-
-    @Override
-    public void addFactory(final FacetFactory facetFactory, final Position position) {
-        addFactory((Object)facetFactory, position);
-    }
-
-    private void addFactory(final Object facetFactoryInstanceOrClass, final Position position) {
-        assertNotInitialized();
-        if(deprecatedPolicy == DeprecatedPolicy.IGNORE) {
-            if( facetFactoryInstanceOrClass instanceof FacetFactory) {
-                if(facetFactoryInstanceOrClass instanceof DeprecatedMarker) {
-                    return;
-                }
-            } else if (facetFactoryInstanceOrClass instanceof Class) {
-                if(DeprecatedMarker.class.isAssignableFrom((Class<?>)facetFactoryInstanceOrClass)) {
-                    return;
-                }
+    
+    private final SetMultimap<ProcessingOrder, FactoryEntry<?>> 
+        factoryEntriesByOrder = _Multimaps.newSetMultimap(LinkedHashSet::new);
+    
+    private List<FacetFactory> snapshot(Predicate<FactoryEntry<?>> filter) {
+        val factories = _Lists.<FacetFactory>newArrayList();
+        for(val processinOrder : ProcessingOrder.values()) {
+            val factoryEntrySet = factoryEntriesByOrder.get(processinOrder);
+            if(factoryEntrySet==null) {
+                continue;
             }
-        }
-        switch (position){
-        case BEGINNING:
-            facetFactoryInstancesOrClasses.add(0, facetFactoryInstanceOrClass);
-            break;
-        case END:
-            facetFactoryInstancesOrClasses.add(facetFactoryInstanceOrClass);
-        }
-    }
-
-
-    @Override
-    public final void removeFactory(final Class<? extends FacetFactory> factoryClass) {
-        assertNotInitialized();
-        for (Iterator<Object> iterator = facetFactoryInstancesOrClasses.iterator(); iterator.hasNext(); ) {
-            final Object factoryInstanceOrClass = iterator.next();
-            if(factoryInstanceOrClass == factoryClass || factoryClass.isAssignableFrom(factoryInstanceOrClass.getClass())) {
-                iterator.remove();
+            for(val factoryEntry : factoryEntrySet) {
+                if(filter.test(factoryEntry)) {
+                    factories.add(factoryEntry.getFactoryInstance());
+                }
             }
         }
+        return factories;
     }
 
-    @Override
-    public void refineMetaModelValidator(final MetaModelValidatorComposite metaModelValidator) {
-        for (final FacetFactory facetFactory : getList()) {
-            if(facetFactory instanceof MetaModelValidatorRefiner) {
-                final MetaModelValidatorRefiner metaModelValidatorRefiner = (MetaModelValidatorRefiner) facetFactory;
-                metaModelValidatorRefiner.refineMetaModelValidator(metaModelValidator);
-            }
-        }
-    }
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelAbstractLegacy.java
similarity index 92%
copy from core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelAbstract.java
copy to core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelAbstractLegacy.java
index 224dbde..7065812 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelAbstractLegacy.java
@@ -22,6 +22,7 @@ package org.apache.isis.metamodel.progmodel;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.function.Predicate;
 
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.factory.InstanceUtil;
@@ -29,7 +30,11 @@ import org.apache.isis.metamodel.facetapi.MetaModelValidatorRefiner;
 import org.apache.isis.metamodel.facets.FacetFactory;
 import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorComposite;
 
-public abstract class ProgrammingModelAbstract implements ProgrammingModel {
+import lombok.val;
+
+@Deprecated
+abstract class ProgrammingModelAbstractLegacy 
+implements ProgrammingModel, FacetFactorySet {
 
     private final List<FacetFactory> facetFactories = _Lists.newArrayList();
     private final List<Object> facetFactoryInstancesOrClasses = _Lists.newLinkedList();
@@ -41,14 +46,14 @@ public abstract class ProgrammingModelAbstract implements ProgrammingModel {
 
     protected final DeprecatedPolicy deprecatedPolicy;
 
-    public ProgrammingModelAbstract(
+    public ProgrammingModelAbstractLegacy(
             final DeprecatedPolicy deprecatedPolicy) {
 
         this.deprecatedPolicy = deprecatedPolicy;
     }
 
     @Override
-    public void init() {
+    public void init(Predicate<FactoryEntry<?>> filter, MetaModelValidatorComposite mmValidator) {
         initializeIfRequired();
     }
 
@@ -143,11 +148,11 @@ public abstract class ProgrammingModelAbstract implements ProgrammingModel {
         }
     }
 
-    @Override
+    //@Override
     public void refineMetaModelValidator(final MetaModelValidatorComposite metaModelValidator) {
-        for (final FacetFactory facetFactory : getList()) {
+        for (val facetFactory : getList()) {
             if(facetFactory instanceof MetaModelValidatorRefiner) {
-                final MetaModelValidatorRefiner metaModelValidatorRefiner = (MetaModelValidatorRefiner) facetFactory;
+                val metaModelValidatorRefiner = (MetaModelValidatorRefiner) facetFactory;
                 metaModelValidatorRefiner.refineMetaModelValidator(metaModelValidator);
             }
         }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelPlugin.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelPlugin.java
index c73b206..c67f65e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelPlugin.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelPlugin.java
@@ -18,83 +18,9 @@
  */
 package org.apache.isis.metamodel.progmodel;
 
-import java.util.Collections;
-import java.util.Objects;
-import java.util.Set;
+@Deprecated // use the MetaModelRefiner interface instead, then provision with Spring
+interface ProgrammingModelPlugin {
 
-import org.apache.isis.commons.internal.collections._Multimaps;
-import org.apache.isis.commons.internal.collections._Multimaps.SetMultimap;
-import org.apache.isis.metamodel.facets.FacetFactory;
-
-public interface ProgrammingModelPlugin {
-
-    // -- CONTRACT
-
-    /**
-     * Guides the priority at which facet factories are registered.
-     * There is no other use.
-     * @apiNote extend as needed
-     */
-    public static enum FacetFactoryCategory {
-        /**
-         * registers the provided factory after built-in value factory providers
-         */
-        VALUE,
-        
-        /**
-         * registers the provided factory after all built-in factories
-         */
-        AFTER_BUILT_IN,
-        ;
-    }
-
-    public static interface FactoryCollector {
-
-        /**
-         *
-         * @param factoryClass
-         * @param category
-         */
-        public void addFactory(FacetFactory facetFactory, final FacetFactoryCategory category);
-
-        /**
-         *
-         * @param category
-         * @return
-         */
-        public Set<FacetFactory> getFactories(FacetFactoryCategory category);
-
-    }
-
-    public static FactoryCollector newCollector() {
-        return new FactoryCollector() {
-
-            final SetMultimap<FacetFactoryCategory, FacetFactory> factoriesByCategory =
-                    _Multimaps.newSetMultimap();
-
-            @Override
-            public void addFactory(FacetFactory factory, FacetFactoryCategory category) {
-                Objects.requireNonNull(factory);
-                Objects.requireNonNull(category);
-                factoriesByCategory.putElement(category, factory);
-            }
-
-            @Override
-            public Set<FacetFactory> getFactories(final FacetFactoryCategory category) {
-                if(category==null) {
-                    return Collections.emptySet();
-                }
-                return Collections.unmodifiableSet(
-                        factoriesByCategory.getOrDefault(category, Collections.emptySet())	);
-
-            }
-        };
-    }
-
-    // -- INTERFACE
-
-    public void plugin(FactoryCollector collector);
-
-    // --
+    public void plugInto(ProgrammingModel programmingModel);
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelService.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelService.java
index f708581..abae641 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelService.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodel/ProgrammingModelService.java
@@ -20,9 +20,13 @@ package org.apache.isis.metamodel.progmodel;
 
 import java.util.function.Supplier;
 
+import org.apache.isis.metamodel.specloader.validator.MetaModelValidator;
+
 /**
  * @since 2.0
  */
 public interface ProgrammingModelService extends Supplier<ProgrammingModel> {
 
+    MetaModelValidator getMetaModelValidator();
+    
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
index 65c07a5..d7e8856 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
@@ -17,12 +17,6 @@
 
 package org.apache.isis.metamodel.progmodels.dflt;
 
-import java.util.List;
-
-import org.apache.isis.applib.annotation.Action;
-import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.commons.internal.context._Plugin;
-import org.apache.isis.commons.internal.reflection._Annotations;
 import org.apache.isis.metamodel.facets.actions.action.ActionAnnotationFacetFactory;
 import org.apache.isis.metamodel.facets.actions.action.ActionChoicesForCollectionParameterFacetFactory;
 import org.apache.isis.metamodel.facets.actions.defaults.method.ActionDefaultsFacetViaMethodFactory;
@@ -72,13 +66,9 @@ import org.apache.isis.metamodel.facets.object.grid.GridFacetFactory;
 import org.apache.isis.metamodel.facets.object.hidden.method.HiddenObjectFacetViaMethodFactory;
 import org.apache.isis.metamodel.facets.object.icon.method.IconFacetMethodFactory;
 import org.apache.isis.metamodel.facets.object.ignore.annotation.RemoveAnnotatedMethodsFacetFactory;
-import org.apache.isis.metamodel.facets.object.ignore.datanucleus.RemoveDatanucleusPersistableTypesFacetFactory;
-import org.apache.isis.metamodel.facets.object.ignore.datanucleus.RemoveDnPrefixedMethodsFacetFactory;
 import org.apache.isis.metamodel.facets.object.ignore.isis.RemoveStaticGettersAndSettersFacetFactory;
 import org.apache.isis.metamodel.facets.object.ignore.javalang.IteratorFilteringFacetFactory;
 import org.apache.isis.metamodel.facets.object.ignore.javalang.RemoveMethodsFacetFactory;
-import org.apache.isis.metamodel.facets.object.ignore.jdo.RemoveJdoEnhancementTypesFacetFactory;
-import org.apache.isis.metamodel.facets.object.ignore.jdo.RemoveJdoPrefixedMethodsFacetFactory;
 import org.apache.isis.metamodel.facets.object.layout.LayoutFacetFactory;
 import org.apache.isis.metamodel.facets.object.mixin.MixinFacetForMixinAnnotationFactory;
 import org.apache.isis.metamodel.facets.object.navparent.annotation.NavigableParentAnnotationFacetFactory;
@@ -156,284 +146,220 @@ import org.apache.isis.metamodel.facets.value.timestampsql.JavaSqlTimeStampValue
 import org.apache.isis.metamodel.facets.value.url.URLValueFacetUsingSemanticsProviderFactory;
 import org.apache.isis.metamodel.facets.value.uuid.UUIDValueFacetUsingSemanticsProviderFactory;
 import org.apache.isis.metamodel.postprocessors.param.DeriveFacetsPostProcessor;
-import org.apache.isis.metamodel.progmodel.ObjectSpecificationPostProcessor;
 import org.apache.isis.metamodel.progmodel.ProgrammingModelAbstract;
-import org.apache.isis.metamodel.progmodel.ProgrammingModelPlugin;
-import org.apache.isis.metamodel.progmodel.ProgrammingModelPlugin.FacetFactoryCategory;
-import org.apache.isis.metamodel.progmodel.ProgrammingModelPlugin.FactoryCollector;
-
-import lombok.val;
 
 public final class ProgrammingModelFacetsJava8 extends ProgrammingModelAbstract {
 
-    public ProgrammingModelFacetsJava8(final DeprecatedPolicy deprecatedPolicy) {
-        super(deprecatedPolicy);
-
-        final FactoryCollector factoriesFromPlugins = discoverFactories();
+    public ProgrammingModelFacetsJava8() {
 
         // must be first, so any Facets created can be replaced by other
         // FacetFactorys later.
-        addFactory(new FallbackFacetFactory());
-
-        addFactory(new ObjectSpecIdFacetDerivedFromClassNameFactory());
-        addFactory(new DomainServiceFacetAnnotationFactory());
-
-        addFactory(new IteratorFilteringFacetFactory());
+        add(ProcessingOrder.A1_FALLBACK_DEFAULTS, FallbackFacetFactory.class);
+        
+        add(ProcessingOrder.B1_OBJECT_NAMING, ObjectSpecIdFacetDerivedFromClassNameFactory.class);
+        add(ProcessingOrder.B1_OBJECT_NAMING, DomainServiceFacetAnnotationFactory.class);
 
-        addFactory(new RemoveMethodsFacetFactory());
+        add(ProcessingOrder.C1_METHOD_REMOVING, IteratorFilteringFacetFactory.class);
 
-        addFactory(new RemoveStaticGettersAndSettersFacetFactory());
+        add(ProcessingOrder.C1_METHOD_REMOVING, RemoveMethodsFacetFactory.class);
 
-        addFactory(new RemoveAnnotatedMethodsFacetFactory());
+        add(ProcessingOrder.C1_METHOD_REMOVING, RemoveStaticGettersAndSettersFacetFactory.class, Marker.DEPRECATED);
 
-        // come what may, we have to ignore the PersistenceCapable supertype.
-        addFactory(new RemoveJdoEnhancementTypesFacetFactory());
-        // so we may as well also just ignore any 'jdo' prefixed methods here also.
-        addFactory(new RemoveJdoPrefixedMethodsFacetFactory());
-        // DN 4.x
-        addFactory(new RemoveDatanucleusPersistableTypesFacetFactory());
-        addFactory(new RemoveDnPrefixedMethodsFacetFactory());
+        add(ProcessingOrder.C1_METHOD_REMOVING, RemoveAnnotatedMethodsFacetFactory.class);
 
-        // must be before any other FacetFactories that install
-        // MandatoryFacet.class facets
-        addFactory(new MandatoryFacetOnProperyDefaultFactory());
-        addFactory(new MandatoryFacetOnParametersDefaultFactory());
+        // must be before any other FacetFactories that install MandatoryFacet.class facets
+        add(ProcessingOrder.D1_MANDATORY_SUPPORT, MandatoryFacetOnProperyDefaultFactory.class);
+        add(ProcessingOrder.D1_MANDATORY_SUPPORT, MandatoryFacetOnParametersDefaultFactory.class);
 
-        addFactory(new PropertyValidateFacetDefaultFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, PropertyValidateFacetDefaultFactory.class);
 
         // enum support
-        addFactory(new EnumFacetUsingValueFacetUsingSemanticsProviderFactory());
-        // addFactory(new ActionParameterChoicesFacetDerivedFromChoicesFacetFactory()); ... moved into post-processor, see below
-        // addFactory(new PropertyChoicesFacetDerivedFromChoicesFacetFactory()); ... moved into post-processor, see below
+        add(ProcessingOrder.E1_MEMBER_MODELLING, EnumFacetUsingValueFacetUsingSemanticsProviderFactory.class);
 
         // properties
-        addFactory(new PropertyAccessorFacetViaAccessorFactory());
-        addFactory(new PropertySetAndClearFacetFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, PropertyAccessorFacetViaAccessorFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, PropertySetAndClearFacetFactory.class);
         // must come after PropertySetAndClearFacetFactory (replaces setter facet with modify if need be)
-        addFactory(new PropertyModifyFacetFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, PropertyModifyFacetFactory.class);
 
-        addFactory(new PropertyValidateFacetViaMethodFactory());
-        addFactory(new PropertyChoicesFacetViaMethodFactory());
-        addFactory(new PropertyAutoCompleteFacetMethodFactory());
-        addFactory(new PropertyDefaultFacetViaMethodFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, PropertyValidateFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, PropertyChoicesFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, PropertyAutoCompleteFacetMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, PropertyDefaultFacetViaMethodFactory.class);
 
         // collections
-        addFactory(new CollectionAccessorFacetViaAccessorFactory());
-        addFactory(new CollectionClearFacetFactory());
-        addFactory(new CollectionAddToRemoveFromAndValidateFacetFactory());
-
-        addFactory(new SortedByFacetAnnotationFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, CollectionAccessorFacetViaAccessorFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, CollectionClearFacetFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, CollectionAddToRemoveFromAndValidateFacetFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, SortedByFacetAnnotationFactory.class);
 
         // actions
-
-        addFactory(new ActionParameterHiddenFacetViaMethodFactory());
-        addFactory(new ActionParameterDisabledFacetViaMethodFactory());
-        addFactory(new ActionValidationFacetViaMethodFactory());
-        addFactory(new ActionParameterValidationFacetViaMethodFactory());
-        addFactory(new ActionChoicesFacetViaMethodFactory());
-        addFactory(new ActionParameterChoicesFacetViaMethodFactory());
-        addFactory(new ActionParameterAutoCompleteFacetViaMethodFactory());
-        addFactory(new ActionDefaultsFacetViaMethodFactory());
-        addFactory(new ActionParameterDefaultsFacetViaMethodFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ActionParameterHiddenFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ActionParameterDisabledFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ActionValidationFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ActionParameterValidationFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ActionChoicesFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ActionParameterChoicesFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ActionParameterAutoCompleteFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ActionDefaultsFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ActionParameterDefaultsFacetViaMethodFactory.class);
 
         // members in general
+        add(ProcessingOrder.E1_MEMBER_MODELLING, DisableForSessionFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, DisableForContextFacetViaMethodFactory.class);
 
-        addFactory(new DisableForSessionFacetViaMethodFactory());
-        addFactory(new DisableForContextFacetViaMethodFactory());
-
-        addFactory(new HideForSessionFacetViaMethodFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, HideForSessionFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, HideForContextFacetViaMethodFactory.class);
 
-        addFactory(new HideForContextFacetViaMethodFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, CreatedCallbackFacetFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, LoadCallbackFacetFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, PersistCallbackViaSaveMethodFacetFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, PersistCallbackFacetFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, UpdateCallbackFacetFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, RemoveCallbackFacetFactory.class);
 
-        addFactory(new CreatedCallbackFacetFactory());
-        addFactory(new LoadCallbackFacetFactory());
-        addFactory(new PersistCallbackViaSaveMethodFacetFactory());
-        addFactory(new PersistCallbackFacetFactory());
-        addFactory(new UpdateCallbackFacetFactory());
-        addFactory(new RemoveCallbackFacetFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ValidateObjectFacetMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ObjectValidPropertiesFacetImplFactory.class);
 
-        addFactory(new ValidateObjectFacetMethodFactory());
-        addFactory(new ObjectValidPropertiesFacetImplFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, MemberOrderFacetFactory.class);
 
-        addFactory(new MemberOrderFacetFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, BookmarkPolicyFacetFallbackFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, HomePageFacetAnnotationFactory.class);
 
-        addFactory(new BookmarkPolicyFacetFallbackFactory());
-        addFactory(new HomePageFacetAnnotationFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, DefaultedFacetAnnotationElseConfigurationFactory.class);
 
-        addFactory(new DefaultedFacetAnnotationElseConfigurationFactory());
-        //addFactory(new PropertyDefaultFacetDerivedFromTypeFactory()); ... logic moved to post-processor
-        //addFactory(new ActionParameterDefaultFacetDerivedFromTypeFactory()); ... logic moved to post-processor
+        add(ProcessingOrder.E1_MEMBER_MODELLING, DescribedAsFacetOnMemberFactory.class);
 
+        add(ProcessingOrder.E1_MEMBER_MODELLING, BigDecimalFacetOnParameterFromJavaxValidationAnnotationFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, BigDecimalFacetOnPropertyFromJavaxValidationDigitsAnnotationFactory.class);
 
-        addFactory(new DescribedAsFacetOnMemberFactory());
-        //addFactory(new DescribedAsFacetOnParameterAnnotationElseDerivedFromTypeFactory()); ... logic moved to post-processor
-
-        addFactory(new BigDecimalFacetOnParameterFromJavaxValidationAnnotationFactory());
-        addFactory(new BigDecimalFacetOnPropertyFromJavaxValidationDigitsAnnotationFactory());
-
-        addFactory(new NotContributedFacetDerivedFromDomainServiceFacetFactory());
-        addFactory(new NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, NotContributedFacetDerivedFromDomainServiceFacetFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory.class);
 
 
         // must come after CssClassFacetOnMemberFactory
-        addFactory(new CssClassFacetOnActionFromConfiguredRegexFactory());
-
-        // addFactory(new CssClassFaFacetOnTypeAnnotationFactory());
-        addFactory(new CssClassFaFacetOnMemberFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, CssClassFacetOnActionFromConfiguredRegexFactory.class);
 
-        addFactory(new HiddenObjectFacetViaMethodFactory());
-        addFactory(new DisabledObjectFacetViaMethodFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, CssClassFaFacetOnMemberFactory.class);
 
-        // addFactory(new CopyImmutableFacetOntoMembersFactory()); ... logic moved to post-processor
+        add(ProcessingOrder.E1_MEMBER_MODELLING, HiddenObjectFacetViaMethodFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, DisabledObjectFacetViaMethodFactory.class);
 
-        addFactory(new RecreatableObjectFacetFactory());
-        addFactory(new JaxbFacetFactory());
-        addFactory(new MixinFacetForMixinAnnotationFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, RecreatableObjectFacetFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, JaxbFacetFactory.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, MixinFacetForMixinAnnotationFactory.class);
 
 
         // must come after RecreatableObjectFacetFactory
-        addFactory(new DomainObjectAnnotationFacetFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, DomainObjectAnnotationFacetFactory.class);
 
         // must come after the property/collection accessor+mutator facet factories
-        addFactory(new ActionAnnotationFacetFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ActionAnnotationFacetFactory.class);
         // after the ActionAnnotationFacetFactory so that takes precedent for contributed associations
-        addFactory(new PropertyAnnotationFacetFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, PropertyAnnotationFacetFactory.class);
         // after the ActionAnnotationFacetFactory so that takes precedent for contributed associations
-        addFactory(new CollectionAnnotationFacetFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, CollectionAnnotationFacetFactory.class);
 
-        addFactory(new ParameterNameFacetFactoryUsingReflection());
-        addFactory(new ParameterAnnotationFacetFactory());
-
-        // must come after DomainObjectAnnotationFacetFactory
-        //addFactory(new DisabledFacetOnPropertyDerivedFromRecreatableObjectFacetFactory()); ... moved to post-processor
-        //addFactory(new DisabledFacetOnCollectionDerivedFromViewModelFacetFactory()); ... moved to post-processor
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ParameterNameFacetFactoryUsingReflection.class);
+        add(ProcessingOrder.E1_MEMBER_MODELLING, ParameterAnnotationFacetFactory.class);
 
         // must come after DomainObjectAnnotationFacetFactory & MixinFacetFactory
-        addFactory(new NotContributedFacetDerivedFromMixinFacetFactory());
+        add(ProcessingOrder.E1_MEMBER_MODELLING, NotContributedFacetDerivedFromMixinFacetFactory.class);
 
-        addFactory(new GridFacetFactory());
+        add(ProcessingOrder.F1_LAYOUT, GridFacetFactory.class);
 
         // must come before DomainObjectLayoutFacetFactory
         // (so subscribers on titleUi event etc can override)
-        addFactory(new TitleAnnotationFacetFactory());
-        addFactory(new TitleFacetViaMethodsFactory());
-        addFactory(new IconFacetMethodFactory());
-        addFactory(new NavigableParentAnnotationFacetFactory());
-        addFactory(new CssClassFacetMethodFactory());
-        addFactory(new LayoutFacetFactory());
+        add(ProcessingOrder.F1_LAYOUT, TitleAnnotationFacetFactory.class);
+        add(ProcessingOrder.F1_LAYOUT, TitleFacetViaMethodsFactory.class);
+        add(ProcessingOrder.F1_LAYOUT, IconFacetMethodFactory.class);
+        add(ProcessingOrder.F1_LAYOUT, NavigableParentAnnotationFacetFactory.class);
+        add(ProcessingOrder.F1_LAYOUT, CssClassFacetMethodFactory.class);
+        add(ProcessingOrder.F1_LAYOUT, LayoutFacetFactory.class);
 
-        addFactory(new DomainServiceLayoutFacetFactory());
-        addFactory(new DomainObjectLayoutFacetFactory());
+        add(ProcessingOrder.F1_LAYOUT, DomainServiceLayoutFacetFactory.class);
+        add(ProcessingOrder.F1_LAYOUT, DomainObjectLayoutFacetFactory.class);
 
         // must come after MultiLine
-        addFactory(new PropertyLayoutFacetFactory());
-        addFactory(new ParameterLayoutFacetFactory());
-        addFactory(new ActionLayoutFacetFactory());
-        addFactory(new CollectionLayoutFacetFactory());
-
-
-        // addFactory(new TypicalLengthFacetOnPropertyDerivedFromTypeFacetFactory()); ... logic moved to post-processor
-        // addFactory(new TypicalLengthFacetOnParameterDerivedFromTypeFacetFactory()); ... logic moved to post-processor
+        add(ProcessingOrder.F1_LAYOUT, PropertyLayoutFacetFactory.class);
+        add(ProcessingOrder.F1_LAYOUT, ParameterLayoutFacetFactory.class);
+        add(ProcessingOrder.F1_LAYOUT, ActionLayoutFacetFactory.class);
+        add(ProcessingOrder.F1_LAYOUT, CollectionLayoutFacetFactory.class);
 
 
         // built-in value types for Java language
-        addFactory(new BooleanPrimitiveValueFacetUsingSemanticsProviderFactory());
-        addFactory(new BooleanWrapperValueFacetUsingSemanticsProviderFactory());
-        addFactory(new BytePrimitiveValueFacetUsingSemanticsProviderFactory());
-        addFactory(new ByteWrapperValueFacetUsingSemanticsProviderFactory());
-        addFactory(new ShortPrimitiveValueFacetUsingSemanticsProviderFactory());
-        addFactory(new ShortWrapperValueFacetUsingSemanticsProviderFactory());
-        addFactory(new IntPrimitiveValueFacetUsingSemanticsProviderFactory());
-        addFactory(new IntWrapperValueFacetUsingSemanticsProviderFactory());
-        addFactory(new LongPrimitiveValueFacetUsingSemanticsProviderFactory());
-        addFactory(new LongWrapperValueFacetUsingSemanticsProviderFactory());
-        addFactory(new FloatPrimitiveValueFacetUsingSemanticsProviderFactory());
-        addFactory(new FloatWrapperValueFacetUsingSemanticsProviderFactory());
-        addFactory(new DoublePrimitiveValueFacetUsingSemanticsProviderFactory());
-        addFactory(new DoubleWrapperValueFacetUsingSemanticsProviderFactory());
-        addFactory(new CharPrimitiveValueFacetUsingSemanticsProviderFactory());
-        addFactory(new CharWrapperValueFacetUsingSemanticsProviderFactory());
-        addFactory(new BigIntegerValueFacetUsingSemanticsProviderFactory());
-        addFactory(new BigDecimalValueFacetUsingSemanticsProviderFactory());
-        addFactory(new JavaSqlDateValueFacetUsingSemanticsProviderFactory());
-        addFactory(new JavaSqlTimeValueFacetUsingSemanticsProviderFactory());
-        addFactory(new JavaSqlTimeStampValueFacetUsingSemanticsProviderFactory());
-        addFactory(new JavaUtilDateValueFacetUsingSemanticsProviderFactory());
-        addFactory(new StringValueFacetUsingSemanticsProviderFactory());
-        addFactory(new URLValueFacetUsingSemanticsProviderFactory());
-        addFactory(new LocalResourcePathValueFacetUsingSemanticsProviderFactory());
-        addFactory(new UUIDValueFacetUsingSemanticsProviderFactory());
-
-        addFactory(new JavaAwtImageValueFacetUsingSemanticsProviderFactory());
+        add(ProcessingOrder.G1_VALUE_TYPES, BooleanPrimitiveValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, BooleanWrapperValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, BytePrimitiveValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, ByteWrapperValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, ShortPrimitiveValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, ShortWrapperValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, IntPrimitiveValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, IntWrapperValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, LongPrimitiveValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, LongWrapperValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, FloatPrimitiveValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, FloatWrapperValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, DoublePrimitiveValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, DoubleWrapperValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, CharPrimitiveValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, CharWrapperValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, BigIntegerValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, BigDecimalValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, JavaSqlDateValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, JavaSqlTimeValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, JavaSqlTimeStampValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, JavaUtilDateValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, StringValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, URLValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, LocalResourcePathValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, UUIDValueFacetUsingSemanticsProviderFactory.class);
+
+        add(ProcessingOrder.G1_VALUE_TYPES, JavaAwtImageValueFacetUsingSemanticsProviderFactory.class);
 
         // applib values
-        addFactory(new BlobValueFacetUsingSemanticsProviderFactory());
-        addFactory(new ClobValueFacetUsingSemanticsProviderFactory());
-        addFactory(new ColorValueFacetUsingSemanticsProviderFactory());
-        addFactory(new MoneyValueFacetUsingSemanticsProviderFactory());
-        addFactory(new PasswordValueFacetUsingSemanticsProviderFactory());
-        addFactory(new PercentageValueFacetUsingSemanticsProviderFactory());
-        addFactory(new ImageValueFacetUsingSemanticsProviderFactory());
+        add(ProcessingOrder.G1_VALUE_TYPES, BlobValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, ClobValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, ColorValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, MoneyValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, PasswordValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, PercentageValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, ImageValueFacetUsingSemanticsProviderFactory.class);
 
         // jodatime values
-        addFactory(new JodaLocalDateValueFacetUsingSemanticsProviderFactory());
-        addFactory(new JodaLocalDateTimeValueFacetUsingSemanticsProviderFactory());
-        addFactory(new JodaDateTimeValueFacetUsingSemanticsProviderFactory());
-        addFactory(new JodaLocalTimeValueFacetSimpleFactory());
+        add(ProcessingOrder.G1_VALUE_TYPES, JodaLocalDateValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, JodaLocalDateTimeValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, JodaDateTimeValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, JodaLocalTimeValueFacetSimpleFactory.class);
 
         // java 8 time values
-        addFactory(new Jdk8LocalDateValueFacetUsingSemanticsProviderFactory());
-        addFactory(new Jdk8OffsetDateTimeValueFacetUsingSemanticsProviderFactory());
-        addFactory(new Jdk8LocalDateTimeValueFacetUsingSemanticsProviderFactory());
-
-        // plugin factories that contribute values
-        factoriesFromPlugins.getFactories(FacetFactoryCategory.VALUE).forEach(this::addFactory);
+        add(ProcessingOrder.G1_VALUE_TYPES, Jdk8LocalDateValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, Jdk8OffsetDateTimeValueFacetUsingSemanticsProviderFactory.class);
+        add(ProcessingOrder.G1_VALUE_TYPES, Jdk8LocalDateTimeValueFacetUsingSemanticsProviderFactory.class);
 
         // written to not trample over TypeOf if already installed
-        addFactory(new CollectionFacetFactory());
+        add(ProcessingOrder.Z1_FINALLY, CollectionFacetFactory.class);
         // must come after CollectionFacetFactory
-        addFactory(new ParentedFacetSinceCollectionFactory());
+        add(ProcessingOrder.Z1_FINALLY, ParentedFacetSinceCollectionFactory.class);
 
         // so we can dogfood the applib "value" types
-        addFactory(new ValueFacetAnnotationOrConfigurationFactory());
+        add(ProcessingOrder.Z1_FINALLY, ValueFacetAnnotationOrConfigurationFactory.class);
 
-        // addFactory(new DisabledFacetOnPropertyDerivedFromImmutableFactory()); ... logic moved to post-processor
-        // addFactory(new DisabledFacetOnCollectionDerivedFromImmutableFactory()); ... logic moved to post-processor
 
         // should come near the end, after any facets that install PropertySetterFacet have run.
-        addFactory(new DisabledFacetOnPropertyInferredFactory());
-
+        add(ProcessingOrder.Z1_FINALLY, DisabledFacetOnPropertyInferredFactory.class);
 
-        addFactory(new ActionChoicesForCollectionParameterFacetFactory());
+        add(ProcessingOrder.Z1_FINALLY, ActionChoicesForCollectionParameterFacetFactory.class);
 
-        addFactory(new FacetsFacetAnnotationFactory());
+        add(ProcessingOrder.Z1_FINALLY, FacetsFacetAnnotationFactory.class);
 
         // must be after all named facets and description facets have been installed
-        addFactory(new TranslationFacetFactory());
+        add(ProcessingOrder.Z1_FINALLY, TranslationFacetFactory.class);
 
-        addFactory(new ViewModelSemanticCheckingFacetFactory());
-        
-        // plugin factories
-        factoriesFromPlugins.getFactories(FacetFactoryCategory.AFTER_BUILT_IN).forEach(this::addFactory);
-
-    }
-
-    @Override
-    public List<ObjectSpecificationPostProcessor> getPostProcessors() {
-        return _Lists.singleton(
-                new DeriveFacetsPostProcessor()
-                );
+        add(ProcessingOrder.Z1_FINALLY, ViewModelSemanticCheckingFacetFactory.class);
+       
+        super.getPostProcessors().add(new DeriveFacetsPostProcessor());
     }
 
-    // -- HELPER
-
-    private static FactoryCollector discoverFactories() {
-        val plugins = _Plugin.loadAll(ProgrammingModelPlugin.class);
-        val collector = ProgrammingModelPlugin.newCollector();
-        plugins.forEach(plugin->{
-            plugin.plugin(collector);
-        });
-        return collector;
-    }
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/MetaModelValidatorServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/MetaModelValidatorServiceDefault.java
index eea4385..1ce8554 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/MetaModelValidatorServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/MetaModelValidatorServiceDefault.java
@@ -20,8 +20,6 @@ package org.apache.isis.metamodel.specloader;
 
 import javax.inject.Inject;
 
-import org.springframework.stereotype.Service;
-
 import org.apache.isis.applib.services.registry.ServiceRegistry;
 import org.apache.isis.commons.internal.base._Lazy;
 import org.apache.isis.commons.internal.factory.InstanceUtil;
@@ -30,7 +28,6 @@ import org.apache.isis.metamodel.facetapi.MetaModelRefiner;
 import org.apache.isis.metamodel.progmodel.ProgrammingModelService;
 import org.apache.isis.metamodel.specloader.validator.MetaModelValidator;
 import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorComposite;
-import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorService;
 
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
@@ -38,10 +35,11 @@ import lombok.extern.log4j.Log4j2;
 /**
  * @since 2.0
  */
-@Service @Log4j2
-public class MetaModelValidatorServiceDefault implements MetaModelValidatorService {
+//@Service 
+@Log4j2
+@Deprecated
+class MetaModelValidatorServiceDefault {
 
-    @Override
     public MetaModelValidator get() {
         return metaModelValidator.get();
     }
@@ -55,7 +53,7 @@ public class MetaModelValidatorServiceDefault implements MetaModelValidatorServi
     private _Lazy<MetaModelValidator> metaModelValidator = 
             _Lazy.threadSafe(this::createMetaModelValidator);
 
-    private MetaModelValidator createMetaModelValidator() {
+    private MetaModelValidatorComposite createMetaModelValidator() {
 
         log.debug("About to create the composite MetaModelValidator.");
         
@@ -67,14 +65,14 @@ public class MetaModelValidatorServiceDefault implements MetaModelValidatorServi
         val mmValidatorComposite = MetaModelValidatorComposite.asComposite(mmValidator);
 
         val programmingModel = programmingModelService.get();
+        //programmingModel.refineMetaModelValidator(mmValidatorComposite);
+        
         val metaModelRefiners = MetaModelRefiner.getAll(serviceRegistry);
 
         for (MetaModelRefiner metaModelRefiner : metaModelRefiners) {
             metaModelRefiner.refineProgrammingModel(programmingModel);
             metaModelRefiner.refineMetaModelValidator(mmValidatorComposite);
         }
-
-        programmingModel.refineMetaModelValidator(mmValidatorComposite);
         
         if(log.isDebugEnabled()) {
             
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/ProgrammingModelServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/ProgrammingModelServiceDefault.java
index cb224ec..6a16bb2 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/ProgrammingModelServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/ProgrammingModelServiceDefault.java
@@ -18,18 +18,26 @@
  */
 package org.apache.isis.metamodel.specloader;
 
+import java.util.EnumSet;
+
 import javax.inject.Inject;
 
-import org.apache.isis.config.IsisConfiguration;
-import org.apache.isis.metamodel.progmodel.ProgrammingModelAbstract;
 import org.springframework.stereotype.Service;
 
+import org.apache.isis.applib.services.registry.ServiceRegistry;
 import org.apache.isis.commons.internal.base._Lazy;
+import org.apache.isis.commons.internal.factory.InstanceUtil;
+import org.apache.isis.config.IsisConfiguration;
 import org.apache.isis.config.IsisConfigurationLegacy;
+import org.apache.isis.metamodel.facetapi.MetaModelRefiner;
+import org.apache.isis.metamodel.facetapi.MetaModelValidatorRefiner;
 import org.apache.isis.metamodel.progmodel.ProgrammingModel;
 import org.apache.isis.metamodel.progmodel.ProgrammingModelService;
 import org.apache.isis.metamodel.progmodels.dflt.ProgrammingModelFacetsJava8;
+import org.apache.isis.metamodel.specloader.validator.MetaModelValidator;
+import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorComposite;
 
+import lombok.Getter;
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
@@ -40,11 +48,16 @@ public class ProgrammingModelServiceDefault implements ProgrammingModelService {
     public ProgrammingModel get() {
         return programmingModel.get();
     }
+    
+    @Getter
+    private MetaModelValidatorComposite metaModelValidator;
 
     // -- HELPER
 
     @Inject private IsisConfigurationLegacy configurationLegacy;
     @Inject private IsisConfiguration configuration;
+    @Inject private ServiceRegistry serviceRegistry;
+     
 
     private _Lazy<ProgrammingModel> programmingModel = 
             _Lazy.threadSafe(this::createProgrammingModel);
@@ -53,23 +66,56 @@ public class ProgrammingModelServiceDefault implements ProgrammingModelService {
         
         log.debug("About to create the ProgrammingModel.");
 
-        boolean ignoreDep = configuration.getReflector().getFacets().isIgnoreDeprecated();
-        val deprecatedPolicy = ignoreDep ? ProgrammingModelAbstract.DeprecatedPolicy.IGNORE : ProgrammingModelAbstract.DeprecatedPolicy.HONOUR;
+        val programmingModel = new ProgrammingModelFacetsJava8();
 
-        val programmingModel = new ProgrammingModelFacetsJava8(deprecatedPolicy);
-        ProgrammingModel.Util.includeFacetFactories(configurationLegacy, programmingModel);
-        ProgrammingModel.Util.excludeFacetFactories(configurationLegacy, programmingModel);
+        val metaModelRefiners = MetaModelRefiner.getAll(serviceRegistry);
+        for (val metaModelRefiner : metaModelRefiners) {
+            metaModelRefiner.refineProgrammingModel(programmingModel);
+        }
+
+        metaModelValidator = createMetaModelValidator();
+        metaModelValidator.init();
+        
+        val isIgnoreDeprecated = configuration.getReflector().getFacets().isIgnoreDeprecated();
+        val excludingMarkers = isIgnoreDeprecated 
+                ? EnumSet.of(ProgrammingModel.Marker.DEPRECATED) 
+                        : null;
+        programmingModel.init(ProgrammingModel.excluding(excludingMarkers), metaModelValidator);
+
+        for (MetaModelRefiner metaModelRefiner : metaModelRefiners) {
+            metaModelRefiner.refineMetaModelValidator(metaModelValidator);
+        }
         
         if(log.isDebugEnabled()) {
             
-            val facetFactoryCount = programmingModel.getList().size();
+            val facetFactoryCount = programmingModel.stream().count();
             val postProcessorCount = programmingModel.getPostProcessors().size();
             
+            val refinerCount = metaModelRefiners.size();
+            val validatorCount = metaModelValidator.size();
+            
+            log.debug("Collected {} validators after also asking {} refiners.",
+                    validatorCount,
+                    refinerCount); 
+            
             log.debug("ProgrammingModel created with {} factories and {} post-processors.", 
                     facetFactoryCount, postProcessorCount);    
         }
         
         return programmingModel;
     }
+    
+    private MetaModelValidatorComposite createMetaModelValidator() {
+
+        log.debug("About to create the composite MetaModelValidator.");
+        
+        val metaModelValidatorClassName =
+                configurationLegacy.getString(
+                        ReflectorConstants.META_MODEL_VALIDATOR_CLASS_NAME,
+                        ReflectorConstants.META_MODEL_VALIDATOR_CLASS_NAME_DEFAULT);
+        val mmValidator = InstanceUtil.createInstance(metaModelValidatorClassName, MetaModelValidator.class);
+        val mmValidatorComposite = MetaModelValidatorComposite.asComposite(mmValidator);
+        return mmValidatorComposite;
+    }
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/ReflectorConstants.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/ReflectorConstants.java
index 9db1c31..1013ce3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/ReflectorConstants.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/ReflectorConstants.java
@@ -49,25 +49,19 @@ public final class ReflectorConstants {
 
     /**
      * Key used to lookup comma-separated list of {@link FacetFactory}s to
-     * include (over and above those specified by
-     * {@link #PROGRAMMING_MODEL_FACETS_CLASS_NAME}.
+     * include.
      *
-     * @see #PROGRAMMING_MODEL_FACETS_CLASS_NAME
      * @see #FACET_FACTORY_EXCLUDE_CLASS_NAME_LIST
      */
-    public static final String FACET_FACTORY_INCLUDE_CLASS_NAME_LIST = ProgrammingModel.FACET_FACTORY_INCLUDE_CLASS_NAME_LIST;
+    public static final String FACET_FACTORY_INCLUDE_CLASS_NAME_LIST = ConfigurationConstants.ROOT + "reflector.facets.include";
 
     /**
      * Key used to lookup comma-separated list of {@link FacetFactory}s to
-     * exclude (that might otherwise be included specified by the
-     * {@link #PROGRAMMING_MODEL_FACETS_CLASS_NAME}.
+     * exclude.
      *
-     * @see #PROGRAMMING_MODEL_FACETS_CLASS_NAME
      * @see #FACET_FACTORY_INCLUDE_CLASS_NAME_LIST
      */
-    public static final String FACET_FACTORY_EXCLUDE_CLASS_NAME_LIST = ProgrammingModel.FACET_FACTORY_EXCLUDE_CLASS_NAME_LIST;
-
-
+    public static final String FACET_FACTORY_EXCLUDE_CLASS_NAME_LIST = ConfigurationConstants.ROOT + "reflector.facets.exclude";
 
     private ReflectorConstants() {
     }
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 1c8089b..9e07932 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
@@ -18,6 +18,8 @@
  */
 package org.apache.isis.metamodel.specloader;
 
+import static org.apache.isis.commons.internal.base._With.requires;
+
 import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -48,12 +50,9 @@ import org.apache.isis.metamodel.specloader.specimpl.IntrospectionState;
 import org.apache.isis.metamodel.specloader.specimpl.dflt.ObjectSpecificationDefault;
 import org.apache.isis.metamodel.specloader.specimpl.standalonelist.ObjectSpecificationOnStandaloneList;
 import org.apache.isis.metamodel.specloader.validator.MetaModelValidator;
-import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorService;
 import org.apache.isis.metamodel.specloader.validator.ValidationFailures;
 import org.apache.isis.schema.utils.CommonDtoUtils;
 
-import static org.apache.isis.commons.internal.base._With.requires;
-
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
@@ -81,17 +80,16 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
     private ProgrammingModel programmingModel;
     private FacetProcessor facetProcessor;
 
-
     private MetaModelValidator metaModelValidator;
+    private PostProcessor postProcessor;
+    
     private final SpecificationCacheDefault<ObjectSpecification> cache = 
             new SpecificationCacheDefault<>();
-    private PostProcessor postProcessor;
 
     @PostConstruct
     public void preInit() {
         this.programmingModel = programmingModelService.get();
-        this.metaModelValidator = metaModelValidatorService.get();
-
+        this.metaModelValidator = programmingModelService.getMetaModelValidator();
         this.facetProcessor = new FacetProcessor(programmingModel);
         this.postProcessor = new PostProcessor(programmingModel);
     }
@@ -132,11 +130,9 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
         }
         
         // initialize subcomponents
-        programmingModel.init();
         facetProcessor.init();
-
         postProcessor.init();
-        metaModelValidator.init();
+        
 
         // need to completely load services and mixins (synchronously)
         log.info("Loading all specs (up to state of {})", IntrospectionState.NOT_INTROSPECTED);
@@ -404,7 +400,6 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
     // -- DEPS
 
     @Inject private ProgrammingModelService programmingModelService;
-    @Inject private MetaModelValidatorService metaModelValidatorService; 
     @Inject private IsisConfiguration isisConfiguration;
     @Inject private IsisSystemEnvironment isisSystemEnvironment;
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/facetprocessor/FacetProcessor.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/facetprocessor/FacetProcessor.java
index 28a04d9..73fc23b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/facetprocessor/FacetProcessor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/facetprocessor/FacetProcessor.java
@@ -129,8 +129,8 @@ public class FacetProcessor {
         cleanUp(); 
         
         serviceInjector = MetaModelContext.current().getServiceInjector();
-        val facetFactoryList = programmingModel.getList();
-        facetFactoryList.forEach(this::registerFactory);
+        programmingModel.stream()
+        .forEach(this::registerFactory);
     }
 
     public void shutdown() {
diff --git a/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/SpecificationLoaderTestAbstract.java b/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/SpecificationLoaderTestAbstract.java
index 0e051c7..9883b2f 100644
--- a/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/SpecificationLoaderTestAbstract.java
+++ b/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/SpecificationLoaderTestAbstract.java
@@ -19,7 +19,10 @@
 
 package org.apache.isis.metamodel.specloader;
 
-import org.apache.isis.metamodel.progmodel.ProgrammingModelAbstract;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.Mockito.when;
+
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -31,6 +34,7 @@ import org.apache.isis.applib.services.i18n.TranslationService.Mode;
 import org.apache.isis.applib.services.message.MessageService;
 import org.apache.isis.commons.internal.base._Timing;
 import org.apache.isis.commons.internal.environment.IsisSystemEnvironment;
+import org.apache.isis.commons.internal.functions._Predicates;
 import org.apache.isis.config.IsisConfiguration;
 import org.apache.isis.metamodel.MetaModelContext;
 import org.apache.isis.metamodel.facetapi.Facet;
@@ -40,15 +44,14 @@ import org.apache.isis.metamodel.facets.all.named.NamedFacet;
 import org.apache.isis.metamodel.facets.collections.modify.CollectionFacet;
 import org.apache.isis.metamodel.facets.object.plural.PluralFacet;
 import org.apache.isis.metamodel.metamodelvalidator.dflt.MetaModelValidatorDefault;
+import org.apache.isis.metamodel.progmodel.ProgrammingModel;
+import org.apache.isis.metamodel.progmodel.ProgrammingModelService;
 import org.apache.isis.metamodel.progmodels.dflt.ProgrammingModelFacetsJava8;
 import org.apache.isis.metamodel.services.persistsession.ObjectAdapterService;
 import org.apache.isis.metamodel.spec.ObjectSpecification;
+import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorComposite;
 import org.apache.isis.security.authentication.AuthenticationSessionProvider;
 
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.mockito.Mockito.when;
-
 import lombok.val;
 
 abstract class SpecificationLoaderTestAbstract {
@@ -88,13 +91,25 @@ abstract class SpecificationLoaderTestAbstract {
             return mock;
         }
 
+        MetaModelValidatorComposite getMetaModelValidatorComposite() {
+            return MetaModelValidatorComposite.asComposite(new MetaModelValidatorDefault());
+        }
+        
+        ProgrammingModel getProgrammingModel() {
+            return  new ProgrammingModelFacetsJava8();
+        }
+        
         //@Produces
-        SpecificationLoader getSpecificationLoader(IsisConfiguration configuration) {
+        SpecificationLoader getSpecificationLoader(
+                IsisConfiguration configuration,
+                ProgrammingModel programmingModel,
+                MetaModelValidatorComposite mmValidator) {
+            
             return SpecificationLoaderDefault.getInstance(
                     configuration,
                     new IsisSystemEnvironment(),
-                    new ProgrammingModelFacetsJava8(ProgrammingModelAbstract.DeprecatedPolicy.HONOUR),
-                    new MetaModelValidatorDefault());
+                    programmingModel,
+                    mmValidator);
         }
 
     }
@@ -118,10 +133,19 @@ abstract class SpecificationLoaderTestAbstract {
         // PRODUCTION
 
         val producers = new Producers();
+        
+        val mmValidator = producers.getMetaModelValidatorComposite(); 
+        val programmingModel = producers.getProgrammingModel();
 
         MetaModelContext.preset(MetaModelContext.builder()
                 .configuration(isisConfiguration = producers.newConfiguration())
-                .specificationLoader(specificationLoader = producers.getSpecificationLoader(isisConfiguration))
+                .specificationLoader(specificationLoader = producers
+                    .getSpecificationLoader(
+                            isisConfiguration,
+                            programmingModel,
+                            mmValidator
+                            )
+                    )
                 .translationService(producers.mockTranslationService())
                 .objectAdapterProvider(mockPersistenceSessionServiceInternal = producers.mockPersistenceSessionServiceInternal())
                 .authenticationSessionProvider(mockAuthenticationSessionProvider = producers.mockAuthenticationSessionProvider())
@@ -129,6 +153,7 @@ abstract class SpecificationLoaderTestAbstract {
                 .singleton(mockGridService = producers.mockGridService())
                 .build());
 
+        programmingModel.init(_Predicates.alwaysTrue(), mmValidator);
 
         _Timing.runVerbose("specificationLoader.init()", specificationLoader::init);
 
diff --git a/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/metamodel/JdoProgrammingModelPlugin.java b/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/metamodel/JdoProgrammingModelPlugin.java
new file mode 100644
index 0000000..80da10f
--- /dev/null
+++ b/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/metamodel/JdoProgrammingModelPlugin.java
@@ -0,0 +1,53 @@
+/*
+ *  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.jdo.metamodel;
+
+import org.springframework.stereotype.Component;
+
+import org.apache.isis.metamodel.facetapi.MetaModelRefiner;
+import org.apache.isis.metamodel.facets.object.ignore.datanucleus.RemoveDatanucleusPersistableTypesFacetFactory;
+import org.apache.isis.metamodel.facets.object.ignore.datanucleus.RemoveDnPrefixedMethodsFacetFactory;
+import org.apache.isis.metamodel.facets.object.ignore.jdo.RemoveJdoEnhancementTypesFacetFactory;
+import org.apache.isis.metamodel.facets.object.ignore.jdo.RemoveJdoPrefixedMethodsFacetFactory;
+import org.apache.isis.metamodel.progmodel.ProgrammingModel;
+import org.apache.isis.metamodel.progmodel.ProgrammingModel.ProcessingOrder;
+import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorComposite;
+
+@Component
+public class JdoProgrammingModelPlugin implements MetaModelRefiner {
+
+    @Override
+    public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator) {
+    }
+
+    @Override
+    public void refineProgrammingModel(ProgrammingModel pm) {
+
+        // come what may, we have to ignore the PersistenceCapable supertype.
+        pm.add(ProcessingOrder.C2_AFTER_METHOD_REMOVING, RemoveJdoEnhancementTypesFacetFactory.class);
+        // so we may as well also just ignore any 'jdo' prefixed methods here also.
+        pm.add(ProcessingOrder.C2_AFTER_METHOD_REMOVING, RemoveJdoPrefixedMethodsFacetFactory.class);
+        // DN 4.x
+        pm.add(ProcessingOrder.C2_AFTER_METHOD_REMOVING, RemoveDatanucleusPersistableTypesFacetFactory.class);
+        pm.add(ProcessingOrder.C2_AFTER_METHOD_REMOVING, RemoveDnPrefixedMethodsFacetFactory.class);
+
+        
+    }
+
+}
diff --git a/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/metamodel/facets/object/domainobject/objectspecid/ObjectSpecIdFacetForJdoPersistenceCapableAnnotation.java b/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/metamodel/facets/object/domainobject/objectspecid/ObjectSpecIdFacetForJdoPersistenceCapableAnnotation.java
index fb3a2bf..a7c2207 100644
--- a/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/metamodel/facets/object/domainobject/objectspecid/ObjectSpecIdFacetForJdoPersistenceCapableAnnotation.java
+++ b/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/metamodel/facets/object/domainobject/objectspecid/ObjectSpecIdFacetForJdoPersistenceCapableAnnotation.java
@@ -29,7 +29,7 @@ import org.apache.isis.metamodel.facets.object.objectspecid.ObjectSpecIdFacetAbs
 
 public class ObjectSpecIdFacetForJdoPersistenceCapableAnnotation extends ObjectSpecIdFacetAbstract {
 
-    public static ObjectSpecIdFacet create(
+    public static ObjectSpecIdFacet create1(
             final JdoPersistenceCapableFacet persistenceCapableFacet,
             final FacetHolder holder) {
 
diff --git a/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/persistence/PersistenceSessionFactoryMetamodelRefiner.java b/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/persistence/PersistenceSessionFactoryMetamodelRefiner.java
index 0fcb110..60794ab 100644
--- a/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/persistence/PersistenceSessionFactoryMetamodelRefiner.java
+++ b/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/persistence/PersistenceSessionFactoryMetamodelRefiner.java
@@ -18,6 +18,8 @@
  */
 package org.apache.isis.jdo.persistence;
 
+import org.springframework.stereotype.Component;
+
 import org.apache.isis.jdo.metamodel.facets.object.datastoreidentity.JdoDatastoreIdentityAnnotationFacetFactory;
 import org.apache.isis.jdo.metamodel.facets.object.discriminator.JdoDiscriminatorAnnotationFacetFactory;
 import org.apache.isis.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableAnnotationFacetFactory;
@@ -35,27 +37,30 @@ import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorComposit
 import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorToCheckModuleExtent;
 import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorToCheckObjectSpecIdsUnique;
 
+@Component
 public class PersistenceSessionFactoryMetamodelRefiner implements MetaModelRefiner {
 
+    final ProgrammingModel.ProcessingOrder order = 
+            ProgrammingModel.ProcessingOrder.A2_AFTER_FALLBACK_DEFAULTS;
+    
     @Override
     public void refineProgrammingModel(ProgrammingModel programmingModel) {
-        programmingModel.addFactory(
-                new JdoPersistenceCapableAnnotationFacetFactory(), ProgrammingModel.Position.BEGINNING);
-        programmingModel.addFactory(new JdoDatastoreIdentityAnnotationFacetFactory());
+        programmingModel.add(order, JdoPersistenceCapableAnnotationFacetFactory.class);
+        programmingModel.add(order, JdoDatastoreIdentityAnnotationFacetFactory.class);
 
-        programmingModel.addFactory(new JdoPrimaryKeyAnnotationFacetFactory());
-        programmingModel.addFactory(new JdoNotPersistentAnnotationFacetFactory());
-        programmingModel.addFactory(new JdoDiscriminatorAnnotationFacetFactory());
-        programmingModel.addFactory(new JdoVersionAnnotationFacetFactory());
+        programmingModel.add(order, JdoPrimaryKeyAnnotationFacetFactory.class);
+        programmingModel.add(order, JdoNotPersistentAnnotationFacetFactory.class);
+        programmingModel.add(order, JdoDiscriminatorAnnotationFacetFactory.class);
+        programmingModel.add(order, JdoVersionAnnotationFacetFactory.class);
 
-        programmingModel.addFactory(new JdoQueryAnnotationFacetFactory());
+        programmingModel.add(order, JdoQueryAnnotationFacetFactory.class);
 
-        programmingModel.addFactory(new BigDecimalDerivedFromJdoColumnAnnotationFacetFactory());
-        programmingModel.addFactory(new MaxLengthDerivedFromJdoColumnAnnotationFacetFactory());
+        programmingModel.add(order, BigDecimalDerivedFromJdoColumnAnnotationFacetFactory.class);
+        programmingModel.add(order, MaxLengthDerivedFromJdoColumnAnnotationFacetFactory.class);
         // must appear after JdoPrimaryKeyAnnotationFacetFactory (above)
         // and also MandatoryFacetOnPropertyMandatoryAnnotationFactory
         // and also PropertyAnnotationFactory
-        programmingModel.addFactory(new MandatoryFromJdoColumnAnnotationFacetFactory());
+        programmingModel.add(order, MandatoryFromJdoColumnAnnotationFacetFactory.class);
     }
 
     @Override
diff --git a/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/IsisBootDataNucleus.java b/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/IsisBootDataNucleus.java
index 092e6c6..c3923cf 100644
--- a/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/IsisBootDataNucleus.java
+++ b/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/IsisBootDataNucleus.java
@@ -33,12 +33,14 @@ import org.apache.isis.jdo.datanucleus.DataNucleusSettings;
 import org.apache.isis.jdo.datanucleus.service.JdoPersistenceLifecycleService;
 import org.apache.isis.jdo.jdosupport.IsisJdoSupportDN5;
 import org.apache.isis.jdo.jdosupport.mixins.Persistable_datanucleusIdLong;
+import org.apache.isis.jdo.metamodel.JdoProgrammingModelPlugin;
 import org.apache.isis.jdo.metrics.MetricsServiceDefault;
 import org.apache.isis.jdo.persistence.IsisPlatformTransactionManagerForJdo;
 
 @Configuration
 @Import({
     DataNucleusSettings.class, // config bean
+    JdoProgrammingModelPlugin.class, // metamodel extensions
     JdoPersistenceLifecycleService.class,
     MetricsServiceDefault.class,
     IsisJdoSupportDN5.class,
diff --git a/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/datanucleus/JDOStateManagerForIsis.java b/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/datanucleus/JDOStateManagerForIsis.java
index 2d68d1f..2552405 100644
--- a/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/datanucleus/JDOStateManagerForIsis.java
+++ b/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/datanucleus/JDOStateManagerForIsis.java
@@ -108,7 +108,7 @@ public class JDOStateManagerForIsis extends ReferentialStateManagerImpl {
     }
 
     @Override
-    public void initialiseForCachedPC(CachedPC cachedPC, Object id) {
+    public void initialiseForCachedPC(CachedPC<Persistable> cachedPC, Object id) {
         super.initialiseForCachedPC(cachedPC, id);
         mapIntoIsis(myPC);
     }
diff --git a/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_datanucleusIdLong.java b/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_datanucleusIdLong.java
index 8d9b712..2640640 100644
--- a/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_datanucleusIdLong.java
+++ b/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_datanucleusIdLong.java
@@ -41,8 +41,7 @@ public class Persistable_datanucleusIdLong {
         this.persistable = persistable;
     }
 
-    public static class ActionDomainEvent extends org.apache.isis.applib.IsisApplibModule.ActionDomainEvent<Persistable_datanucleusIdLong> {
-        private static final long serialVersionUID = 1L;}
+    public static class ActionDomainEvent extends org.apache.isis.applib.IsisApplibModule.ActionDomainEvent<Persistable_datanucleusIdLong> {}
 
     @Action(
             domainEvent = ActionDomainEvent.class,
diff --git a/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_datanucleusVersionLong.java b/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_datanucleusVersionLong.java
index 728af2e..4bae573 100644
--- a/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_datanucleusVersionLong.java
+++ b/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_datanucleusVersionLong.java
@@ -40,8 +40,7 @@ public class Persistable_datanucleusVersionLong {
         this.persistable = persistable;
     }
 
-    public static class ActionDomainEvent extends org.apache.isis.applib.IsisApplibModule.ActionDomainEvent<Persistable_datanucleusVersionLong> {
-        private static final long serialVersionUID = 1L;}
+    public static class ActionDomainEvent extends org.apache.isis.applib.IsisApplibModule.ActionDomainEvent<Persistable_datanucleusVersionLong> {}
 
     @Action(
             domainEvent = ActionDomainEvent.class,
diff --git a/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_datanucleusVersionTimestamp.java b/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_datanucleusVersionTimestamp.java
index 864c673..af99395 100644
--- a/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_datanucleusVersionTimestamp.java
+++ b/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_datanucleusVersionTimestamp.java
@@ -40,8 +40,7 @@ public class Persistable_datanucleusVersionTimestamp {
         this.persistable = persistable;
     }
 
-    public static class ActionDomainEvent extends org.apache.isis.applib.IsisApplibModule.ActionDomainEvent<Persistable_datanucleusVersionTimestamp> {
-        private static final long serialVersionUID = 1L;}
+    public static class ActionDomainEvent extends org.apache.isis.applib.IsisApplibModule.ActionDomainEvent<Persistable_datanucleusVersionTimestamp> {}
 
     @Action(
             domainEvent = ActionDomainEvent.class,
diff --git a/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_downloadJdoMetadata.java b/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_downloadJdoMetadata.java
index b5f1d81..ea709b6 100644
--- a/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_downloadJdoMetadata.java
+++ b/core/plugins/jdo/datanucleus-5/src/main/java/org/apache/isis/jdo/jdosupport/mixins/Persistable_downloadJdoMetadata.java
@@ -48,8 +48,7 @@ public class Persistable_downloadJdoMetadata {
         this.persistable = persistable;
     }
 
-    public static class ActionDomainEvent extends org.apache.isis.applib.IsisApplibModule.ActionDomainEvent<Persistable_downloadJdoMetadata> {
-        private static final long serialVersionUID = 1L;}
+    public static class ActionDomainEvent extends org.apache.isis.applib.IsisApplibModule.ActionDomainEvent<Persistable_downloadJdoMetadata> {}
 
     @Action(
             domainEvent = ActionDomainEvent.class,
diff --git a/examples/smoketests/src/test/resources/org/apache/isis/testdomain/bootstrapping/builtin-singleton.list b/examples/smoketests/src/test/resources/org/apache/isis/testdomain/bootstrapping/builtin-singleton.list
index dae1651..6c0e6a0 100644
--- a/examples/smoketests/src/test/resources/org/apache/isis/testdomain/bootstrapping/builtin-singleton.list
+++ b/examples/smoketests/src/test/resources/org/apache/isis/testdomain/bootstrapping/builtin-singleton.list
@@ -48,7 +48,6 @@ org.apache.isis.metamodel.services.title.TitleServiceDefault
 org.apache.isis.metamodel.services.user.UserServiceDefault
 org.apache.isis.metamodel.services.user.UserServiceDefault$SudoServiceSpi
 org.apache.isis.metamodel.specloader.InjectorMethodEvaluatorDefault
-org.apache.isis.metamodel.specloader.MetaModelValidatorServiceDefault
 org.apache.isis.metamodel.specloader.ProgrammingModelServiceDefault
 org.apache.isis.metamodel.specloader.SpecificationLoaderDefault
 org.apache.isis.runtime.services.authsess.AuthenticationSessionProviderDefault
diff --git a/extensions/incubator/src/main/java/org/apache/isis/extensions/incubator/IncubatorPlugin.java b/extensions/incubator/src/main/java/org/apache/isis/extensions/incubator/IncubatorMetaModelPlugin.java
similarity index 56%
rename from extensions/incubator/src/main/java/org/apache/isis/extensions/incubator/IncubatorPlugin.java
rename to extensions/incubator/src/main/java/org/apache/isis/extensions/incubator/IncubatorMetaModelPlugin.java
index 49bce9f..222ec48 100644
--- a/extensions/incubator/src/main/java/org/apache/isis/extensions/incubator/IncubatorPlugin.java
+++ b/extensions/incubator/src/main/java/org/apache/isis/extensions/incubator/IncubatorMetaModelPlugin.java
@@ -18,17 +18,27 @@
  */
 package org.apache.isis.extensions.incubator;
 
+import org.springframework.stereotype.Component;
+
+import org.apache.isis.metamodel.facetapi.MetaModelRefiner;
 import org.apache.isis.metamodel.facets.actions.support.SupportingMethodValidatorRefinerFactory;
-import org.apache.isis.metamodel.progmodel.ProgrammingModelPlugin;
+import org.apache.isis.metamodel.progmodel.ProgrammingModel;
+import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorComposite;
+
+@Component
+public class IncubatorMetaModelPlugin implements MetaModelRefiner {
 
-public class IncubatorPlugin implements ProgrammingModelPlugin {
+    @Override
+    public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator) {
+    }
 
     @Override
-    public void plugin(FactoryCollector collector) {
-        
-        collector.addFactory(
-                new SupportingMethodValidatorRefinerFactory(), FacetFactoryCategory.AFTER_BUILT_IN);
-        
+    public void refineProgrammingModel(ProgrammingModel programmingModel) {
+        programmingModel.add(
+                ProgrammingModel.ProcessingOrder.C2_AFTER_METHOD_REMOVING, 
+                SupportingMethodValidatorRefinerFactory.class,
+                ProgrammingModel.Marker.INCUBATING
+                );
     }
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorService.java b/extensions/incubator/src/main/java/org/apache/isis/extensions/incubator/IsisBootIncubator.java
similarity index 76%
rename from core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorService.java
rename to extensions/incubator/src/main/java/org/apache/isis/extensions/incubator/IsisBootIncubator.java
index ff31280..a4d9e84 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/validator/MetaModelValidatorService.java
+++ b/extensions/incubator/src/main/java/org/apache/isis/extensions/incubator/IsisBootIncubator.java
@@ -16,13 +16,15 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.metamodel.specloader.validator;
+package org.apache.isis.extensions.incubator;
 
-import java.util.function.Supplier;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
 
-/**
- * @since 2.0
- */
-public interface MetaModelValidatorService extends Supplier<MetaModelValidator>{
+@Configuration
+@Import({
+    IncubatorMetaModelPlugin.class
+})
+public class IsisBootIncubator {
 
 }
diff --git a/extensions/incubator/src/main/resources/META-INF/services/org.apache.isis.metamodel.progmodel.ProgrammingModelPlugin b/extensions/incubator/src/main/resources/META-INF/services/org.apache.isis.metamodel.progmodel.ProgrammingModelPlugin
deleted file mode 100644
index 450593b..0000000
--- a/extensions/incubator/src/main/resources/META-INF/services/org.apache.isis.metamodel.progmodel.ProgrammingModelPlugin
+++ /dev/null
@@ -1 +0,0 @@
-org.apache.isis.extensions.incubator.IncubatorPlugin
\ No newline at end of file
diff --git a/extensions/sse/src/main/java/org/apache/isis/extensions/sse/IsisBootSse.java b/extensions/sse/src/main/java/org/apache/isis/extensions/sse/IsisBootSse.java
index 1546638..d215014 100644
--- a/extensions/sse/src/main/java/org/apache/isis/extensions/sse/IsisBootSse.java
+++ b/extensions/sse/src/main/java/org/apache/isis/extensions/sse/IsisBootSse.java
@@ -26,6 +26,7 @@ import org.apache.isis.extensions.sse.webapp.WebModuleServerSentEvents;
 
 @Configuration
 @Import({
+    SseMetaModelPlugin.class,
     SseServiceDefault.class,
     WebModuleServerSentEvents.class
 })
diff --git a/extensions/sse/src/main/java/org/apache/isis/extensions/sse/SsePlugin.java b/extensions/sse/src/main/java/org/apache/isis/extensions/sse/SseMetaModelPlugin.java
similarity index 57%
rename from extensions/sse/src/main/java/org/apache/isis/extensions/sse/SsePlugin.java
rename to extensions/sse/src/main/java/org/apache/isis/extensions/sse/SseMetaModelPlugin.java
index a26ed0a..fe37d60 100644
--- a/extensions/sse/src/main/java/org/apache/isis/extensions/sse/SsePlugin.java
+++ b/extensions/sse/src/main/java/org/apache/isis/extensions/sse/SseMetaModelPlugin.java
@@ -18,17 +18,26 @@
  */
 package org.apache.isis.extensions.sse;
 
+import org.springframework.stereotype.Component;
+
 import org.apache.isis.extensions.sse.facets.SseAnnotationFacetFactory;
-import org.apache.isis.metamodel.progmodel.ProgrammingModelPlugin;
+import org.apache.isis.metamodel.facetapi.MetaModelRefiner;
+import org.apache.isis.metamodel.progmodel.ProgrammingModel;
+import org.apache.isis.metamodel.specloader.validator.MetaModelValidatorComposite;
+
+@Component
+public class SseMetaModelPlugin implements MetaModelRefiner {
 
-public class SsePlugin implements ProgrammingModelPlugin {
+    @Override
+    public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator) {
+    }
 
     @Override
-    public void plugin(FactoryCollector collector) {
-        
-        collector.addFactory(
-                new SseAnnotationFacetFactory(), FacetFactoryCategory.AFTER_BUILT_IN);
-        
+    public void refineProgrammingModel(ProgrammingModel programmingModel) {
+        programmingModel.add(
+                ProgrammingModel.ProcessingOrder.Z2_AFTER_FINALLY, 
+                SseAnnotationFacetFactory.class, 
+                ProgrammingModel.Marker.INCUBATING);
     }
 
 }
diff --git a/extensions/sse/src/main/resources/META-INF/services/org.apache.isis.metamodel.progmodel.ProgrammingModelPlugin b/extensions/sse/src/main/resources/META-INF/services/org.apache.isis.metamodel.progmodel.ProgrammingModelPlugin
deleted file mode 100644
index a1f7aab..0000000
--- a/extensions/sse/src/main/resources/META-INF/services/org.apache.isis.metamodel.progmodel.ProgrammingModelPlugin
+++ /dev/null
@@ -1 +0,0 @@
-org.apache.isis.extensions.sse.SsePlugin
\ No newline at end of file