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 2022/04/07 06:12:54 UTC

[isis] branch master updated: ISIS-2994: remove all direct facet uses from wicket-ui

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

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


The following commit(s) were added to refs/heads/master by this push:
     new d15b8bbb26 ISIS-2994: remove all direct facet uses from wicket-ui
d15b8bbb26 is described below

commit d15b8bbb26fcb2e79faeeec88759f9112d7c9c3f
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Apr 7 08:12:44 2022 +0200

    ISIS-2994: remove all direct facet uses from wicket-ui
---
 .../apache/isis/core/metamodel/util/Facets.java    | 206 +++++++++++++++++++++
 .../viewer/wicket/model/models/ScalarModel.java    |   2 +
 .../CollectionPresentationSelectorHelper.java      |  34 ++--
 .../CollectionContentsAsIconsPanelFactory.java     |  16 +-
 .../entity/EntityComponentFactoryAbstract.java     |   5 +-
 .../entity/collection/EntityCollectionPanel.java   |  11 +-
 .../components/entity/fieldset/PropertyGroup.java  |  20 +-
 .../ui/components/layout/bs3/BS3GridPanel.java     |  22 +--
 .../components/layout/bs3/Bs3GridPanelFactory.java |  21 +--
 .../ui/components/scalars/ScalarPanelAbstract.java |  32 +---
 .../scalars/ScalarPanelTextFieldAbstract.java      |  50 ++---
 .../ScalarPanelTextFieldWithTemporalPicker.java    |   6 +-
 .../ui/components/scalars/bool/BooleanPanel.java   |   2 +-
 .../scalars/reference/ReferencePanel.java          |  14 +-
 .../scalars/string/StringPanelFactory.java         |  12 +-
 .../value/fallback/ValueFallbackPanelFactory.java  |   5 +-
 ...entoProviderForReferenceObjectAutoComplete.java |  12 +-
 .../viewer/wicket/ui/pages/entity/EntityPage.java  |  21 +--
 18 files changed, 307 insertions(+), 184 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/Facets.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/Facets.java
new file mode 100644
index 0000000000..4fe3069130
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/Facets.java
@@ -0,0 +1,206 @@
+/*
+ *  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.core.metamodel.util;
+
+import java.util.Optional;
+import java.util.OptionalInt;
+import java.util.function.Predicate;
+
+import org.apache.isis.applib.annotation.LabelPosition;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3Grid;
+import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.base._Casts;
+import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
+import org.apache.isis.core.metamodel.facets.collections.collection.defaultview.DefaultViewFacet;
+import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
+import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacet;
+import org.apache.isis.core.metamodel.facets.object.grid.GridFacet;
+import org.apache.isis.core.metamodel.facets.object.icon.IconFacet;
+import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
+import org.apache.isis.core.metamodel.facets.objectvalue.daterenderedadjust.DateRenderAdjustFacet;
+import org.apache.isis.core.metamodel.facets.objectvalue.labelat.LabelAtFacet;
+import org.apache.isis.core.metamodel.facets.objectvalue.maxlen.MaxLengthFacet;
+import org.apache.isis.core.metamodel.facets.objectvalue.multiline.MultiLineFacet;
+import org.apache.isis.core.metamodel.facets.objectvalue.typicallen.TypicalLengthFacet;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectFeature;
+
+import lombok.val;
+import lombok.experimental.UtilityClass;
+
+/**
+ * Facet utility.
+ * <p>
+ * Motivation: Viewers should not use {@link Facet}s directly.
+ */
+@UtilityClass
+public final class Facets {
+
+    public Can<ManagedObject> autoCompleteExecute(
+            final ObjectSpecification objectSpec, final String term) {
+        return objectSpec.lookupFacet(AutoCompleteFacet.class)
+        .map(autoCompleteFacet->autoCompleteFacet.execute(term, InteractionInitiatedBy.USER))
+        .orElseGet(Can::empty);
+    }
+
+    public boolean autoCompleteIsPresent(final ObjectSpecification objectSpec) {
+        return objectSpec.containsFacet(AutoCompleteFacet.class);
+    }
+
+    public OptionalInt autoCompleteMinLength(final ObjectSpecification objectSpec) {
+        return objectSpec.lookupFacet(AutoCompleteFacet.class)
+        .map(AutoCompleteFacet::getMinLength)
+        .map(OptionalInt::of)
+        .orElseGet(OptionalInt::empty);
+    }
+
+    public Optional<BS3Grid> bootstrapGrid(
+            final ObjectSpecification objectSpec, final ManagedObject objectAdapter) {
+        return objectSpec.lookupFacet(GridFacet.class)
+        .map(gridFacet->gridFacet.getGrid(objectAdapter))
+        .flatMap(grid->_Casts.castTo(BS3Grid.class, grid));
+    }
+
+    public Optional<String> cssClassFor(
+            final FacetHolder objectSpec, final ManagedObject objectAdapter) {
+        return objectSpec.lookupFacet(CssClassFacet.class)
+        .map(cssClassFacet->cssClassFacet.cssClass(objectAdapter));
+    }
+
+    public int dateRenderAdjustDays(final ObjectFeature feature) {
+        return feature.lookupFacet(DateRenderAdjustFacet.class)
+        .map(DateRenderAdjustFacet::getDateRenderAdjustDays)
+        .orElse(0);
+    }
+
+    public boolean defaultViewIsPresent(final ObjectFeature feature) {
+        return feature.containsFacet(DefaultViewFacet.class);
+    }
+
+    public boolean defaultViewIsTable(final ObjectFeature feature) {
+        return defaultViewName(feature)
+        .map(viewName->"table".equals(viewName))
+        .orElse(false);
+    }
+
+    public Optional<String> defaultViewName(final ObjectFeature feature) {
+        return feature.lookupFacet(DefaultViewFacet.class)
+        .map(DefaultViewFacet::value);
+    }
+
+    public void gridPreload(
+            final ObjectSpecification objectSpec, final ManagedObject objectAdapter) {
+        objectSpec.lookupFacet(GridFacet.class)
+        .ifPresent(gridFacet->
+            // the facet should always exist, in fact
+            // just enough to ask for the metadata.
+            // This will cause the current ObjectSpec to be updated as a side effect.
+            gridFacet.getGrid(objectAdapter));
+    }
+
+    public Optional<Where> hiddenWhere(final ObjectFeature feature) {
+        return feature.lookupFacet(HiddenFacet.class)
+        .map(HiddenFacet::where);
+    }
+
+    public Predicate<ObjectFeature> hiddenWhereMatches(final Predicate<Where> matcher) {
+        return feature->Facets.hiddenWhere(feature)
+        .map(matcher::test)
+        .orElse(false);
+    }
+
+    public boolean iconIsPresent(final ObjectSpecification objectSpec) {
+        return objectSpec.containsFacet(IconFacet.class);
+    }
+
+    public Optional<LabelPosition> labelAt(final ObjectFeature feature) {
+        return feature.lookupFacet(LabelAtFacet.class)
+        .map(LabelAtFacet::label);
+    }
+
+    public String labelAtCss(final ObjectFeature feature) {
+        return Facets.labelAt(feature)
+        .map(labelPos->{
+            switch (labelPos) {
+            case LEFT:
+                return "label-left";
+            case RIGHT:
+                return "label-right";
+            case NONE:
+                return "label-none";
+            case TOP:
+                return "label-top";
+            case DEFAULT:
+            case NOT_SPECIFIED:
+            default:
+                return "label-left";
+            }
+        })
+        .orElse("label-left");
+    }
+
+    public OptionalInt maxLength(final ObjectSpecification objectSpec) {
+        return objectSpec
+                .lookupFacet(MaxLengthFacet.class)
+                .map(MaxLengthFacet::value)
+                .map(OptionalInt::of)
+                .orElseGet(OptionalInt::empty);
+    }
+
+    public boolean multilineIsPresent(final ObjectFeature feature) {
+        return feature.lookupNonFallbackFacet(MultiLineFacet.class)
+                .isPresent();
+    }
+
+    public OptionalInt multilineNumberOfLines(final ObjectSpecification objectSpec) {
+        return objectSpec
+                .lookupFacet(MultiLineFacet.class)
+                .map(MultiLineFacet::numberOfLines)
+                .map(OptionalInt::of)
+                .orElseGet(OptionalInt::empty);
+    }
+
+    public OptionalInt typicalLength(
+            final ObjectSpecification objectSpec, final OptionalInt maxLength) {
+        val typicalLength = objectSpec
+                .lookupFacet(TypicalLengthFacet.class)
+                .map(TypicalLengthFacet::value)
+                .orElse(null);
+        // doesn't make sense for typical length to be > maxLength
+        final Integer result = (typicalLength != null
+                && maxLength.isPresent()
+                && typicalLength > maxLength.getAsInt())
+                ? maxLength.getAsInt()
+                : typicalLength;
+        return Optional.ofNullable(result)
+                .map(OptionalInt::of)
+                .orElseGet(OptionalInt::empty);
+    }
+
+    public boolean valueIsPresent(final ObjectSpecification objectSpec) {
+        return objectSpec.containsFacet(ValueFacet.class);
+    }
+
+
+}
diff --git a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
index a3530147d5..ebc8e4e8cb 100644
--- a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
+++ b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
@@ -220,10 +220,12 @@ implements HasRenderingHints, ScalarUiModel, LinksProvider, FormExecutorContext
 
     public abstract String getCssClass();
 
+    @Deprecated // viewers should not directly use facets
     public final <T extends Facet> T getFacet(final Class<T> facetType) {
         return getMetaModel().getFacet(facetType);
     }
 
+    @Deprecated // viewers should not directly use facets
     public final <T extends Facet> Optional<T> lookupFacet(final Class<T> facetType) {
         return getMetaModel().lookupFacet(facetType);
     }
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionPresentationSelectorHelper.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionPresentationSelectorHelper.java
index a8ac90c3a4..8096ac879c 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionPresentationSelectorHelper.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionPresentationSelectorHelper.java
@@ -20,7 +20,6 @@ package org.apache.isis.viewer.wicket.ui.components.collection.selector;
 
 import java.io.Serializable;
 import java.util.List;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
@@ -32,8 +31,7 @@ import org.apache.isis.applib.layout.component.CollectionLayoutData;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.commons.collections.ImmutableEnumSet;
 import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.core.metamodel.facets.collections.collection.defaultview.DefaultViewFacet;
-import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.common.model.components.ComponentType;
 import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
@@ -46,7 +44,6 @@ import org.apache.isis.viewer.wicket.ui.components.collectioncontents.multiple.C
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.unresolved.CollectionContentsHiddenPanelFactory;
 
 import lombok.Getter;
-import lombok.val;
 
 public class CollectionPresentationSelectorHelper implements Serializable {
 
@@ -152,10 +149,12 @@ public class CollectionPresentationSelectorHelper implements Serializable {
 
         // else @CollectionLayout#defaultView attribute
         if (hasDefaultViewFacet(collectionModel)) {
-            DefaultViewFacet defaultViewFacet = collectionModel.getMetaModel().getFacet(DefaultViewFacet.class);
+
+            final String viewName = Facets.defaultViewName(collectionModel.getMetaModel())
+                    .orElseThrow(); // null case guarded by if clause
+
             for (ComponentFactory componentFactory : componentFactories) {
                 final String componentName = componentFactory.getName();
-                final String viewName = defaultViewFacet.value();
                 if (componentName.equalsIgnoreCase(viewName)) {
                     return componentName;
                 }
@@ -163,7 +162,7 @@ public class CollectionPresentationSelectorHelper implements Serializable {
         }
 
         // else honour @CollectionLayout#renderEagerly
-        return hasRenderEagerlyFacet(collectionModel)
+        return hasRenderEagerlySemantics(collectionModel)
                 || collectionModel.getVariant().isStandalone()
                     ? CollectionContentsAsAjaxTablePanelFactory.NAME
                     : CollectionContentsHiddenPanelFactory.NAME;
@@ -174,27 +173,18 @@ public class CollectionPresentationSelectorHelper implements Serializable {
         return UiHintContainer.Util.hintContainerOf(component, EntityCollectionModelParented.class);
     }
 
-    private static boolean hasRenderEagerlyFacet(final IModel<?> model) {
+    private static boolean hasRenderEagerlySemantics(final IModel<?> model) {
         return toParentedEntityCollectionModel(model)
         .map(EntityCollectionModelParented::getMetaModel)
-        .map(CollectionPresentationSelectorHelper::isRenderEagerly)
+        .map(Facets::defaultViewIsTable)
         .orElse(false);
     }
 
-    private static boolean isRenderEagerly(final OneToManyAssociation collectionMetaModel) {
-        final DefaultViewFacet defaultViewFacet = collectionMetaModel.getFacet(DefaultViewFacet.class);
-        return defaultViewFacet != null && Objects.equals(defaultViewFacet.value(), "table");
-    }
-
-
     private static boolean hasDefaultViewFacet(final IModel<?> model) {
-        val entityCollectionModel = toParentedEntityCollectionModel(model).orElse(null);
-        if (entityCollectionModel == null) {
-            return false;
-        }
-        final OneToManyAssociation collection = entityCollectionModel.getMetaModel();
-        DefaultViewFacet defaultViewFacet = collection.getFacet(DefaultViewFacet.class);
-        return defaultViewFacet != null;
+        return toParentedEntityCollectionModel(model)
+        .map(EntityCollectionModelParented::getMetaModel)
+        .map(Facets::defaultViewIsPresent)
+        .orElse(false);
     }
 
     public ComponentFactory find(final String selected) {
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/icons/CollectionContentsAsIconsPanelFactory.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/icons/CollectionContentsAsIconsPanelFactory.java
index 5e7d852009..6ec3d9555e 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/icons/CollectionContentsAsIconsPanelFactory.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/icons/CollectionContentsAsIconsPanelFactory.java
@@ -21,13 +21,14 @@ package org.apache.isis.viewer.wicket.ui.components.collectioncontents.icons;
 import org.apache.wicket.Component;
 import org.apache.wicket.model.IModel;
 
-import org.apache.isis.core.metamodel.facets.object.icon.IconFacet;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.common.model.components.ComponentType;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentFactoryAbstract;
 
+import lombok.val;
+
 /**
  * {@link ComponentFactory} for {@link CollectionContentsAsIconsPanel}.
  */
@@ -48,12 +49,11 @@ public class CollectionContentsAsIconsPanelFactory extends ComponentFactoryAbstr
             return ApplicationAdvice.DOES_NOT_APPLY;
         }
 
-        final EntityCollectionModel entityCollectionModel = (EntityCollectionModel) model;
-        final ObjectSpecification typeOfSpec = entityCollectionModel.getElementType();
-        if (typeOfSpec.getFacet(IconFacet.class) == null) {
-            return ApplicationAdvice.DOES_NOT_APPLY;
-        }
-        return ApplicationAdvice.APPLIES;
+        val entityCollectionModel = (EntityCollectionModel) model;
+
+        return Facets.iconIsPresent(entityCollectionModel.getElementType())
+                ? ApplicationAdvice.APPLIES
+                : ApplicationAdvice.DOES_NOT_APPLY;
     }
 
     @Override
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java
index c08ecde462..22834311d9 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java
@@ -21,8 +21,8 @@ package org.apache.isis.viewer.wicket.ui.components.entity;
 import org.apache.wicket.Component;
 import org.apache.wicket.model.IModel;
 
-import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.common.model.components.ComponentType;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.ComponentFactoryAbstract;
@@ -70,7 +70,8 @@ public abstract class EntityComponentFactoryAbstract extends ComponentFactoryAbs
         }
         final ObjectSpecification specification = entityModel.getTypeOfSpecification();
         final boolean isScalar = specification.isScalar();
-        final boolean isValue = specification.containsFacet(ValueFacet.class);
+
+        final boolean isValue = Facets.valueIsPresent(specification);
         if (isScalar && !isValue) {
             return doAppliesTo(entityModel);
         }
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collection/EntityCollectionPanel.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collection/EntityCollectionPanel.java
index 1a3e2c59cc..61f9efa973 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collection/EntityCollectionPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collection/EntityCollectionPanel.java
@@ -32,8 +32,8 @@ import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.core.metamodel.consent.Consent;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
-import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModelParented;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
@@ -45,9 +45,9 @@ import org.apache.isis.viewer.wicket.ui.components.collection.selector.Collectio
 import org.apache.isis.viewer.wicket.ui.components.collection.selector.CollectionPresentationSelectorPanel;
 import org.apache.isis.viewer.wicket.ui.panels.HasDynamicallyVisibleContent;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+import org.apache.isis.viewer.wicket.ui.util.Wkt;
 import org.apache.isis.viewer.wicket.ui.util.WktComponents;
 import org.apache.isis.viewer.wicket.ui.util.WktTooltips;
-import org.apache.isis.viewer.wicket.ui.util.Wkt;
 
 import lombok.val;
 
@@ -120,15 +120,12 @@ implements HasDynamicallyVisibleContent {
 
             visible = true;
 
-            collectionMetaModel.lookupFacet(CssClassFacet.class)
-            .ifPresent(facet->
-                Wkt.cssAppend(div, facet.cssClass(objectAdapter)));
-
+            Facets.cssClassFor(collectionMetaModel, objectAdapter)
+            .ifPresent(cssClass->Wkt.cssAppend(div, cssClass));
 
             final CollectionPanel collectionPanel = newCollectionModel(ID_COLLECTION, collectionModel);
             div.addOrReplace(collectionPanel);
 
-
             final Label labelComponent = collectionPanel
                     .createLabel(
                             ID_COLLECTION_NAME,
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
index 8287177865..2d651392d9 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
@@ -34,10 +34,10 @@ import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.core.metamodel.commons.ScalarRepresentation;
-import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.common.model.components.ComponentType;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
@@ -47,8 +47,8 @@ import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.Link
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract;
 import org.apache.isis.viewer.wicket.ui.panels.HasDynamicallyVisibleContent;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
-import org.apache.isis.viewer.wicket.ui.util.WktComponents;
 import org.apache.isis.viewer.wicket.ui.util.Wkt;
+import org.apache.isis.viewer.wicket.ui.util.WktComponents;
 
 import lombok.val;
 
@@ -170,17 +170,13 @@ public class PropertyGroup extends PanelAbstract<ManagedObject, EntityModel> imp
             .orElse(null)
         )
         .filter(_NullSafe::isPresent)
-        .filter(property -> {
-            val hiddenFacet = property.getFacet(HiddenFacet.class);
-            if(hiddenFacet != null) {
+        .filter(
+            Facets.hiddenWhereMatches(where->
                 // static invisible.
-                if(hiddenFacet.where().isAlways()
-                        || hiddenFacet.where() == Where.OBJECT_FORMS) {
-                    return false;
-                }
-            }
-            return true;
-        })
+                where.isAlways()
+                        || where == Where.OBJECT_FORMS)
+            .negate()
+        )
         .collect(Can.toCan());
     }
 
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/BS3GridPanel.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/BS3GridPanel.java
index 5b52d4a63c..f32db09d9f 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/BS3GridPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/BS3GridPanel.java
@@ -23,14 +23,13 @@ import java.util.Optional;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.repeater.RepeatingView;
 
-import org.apache.isis.applib.layout.grid.Grid;
 import org.apache.isis.applib.layout.grid.bootstrap3.BS3Grid;
 import org.apache.isis.applib.layout.grid.bootstrap3.BS3Row;
-import org.apache.isis.core.metamodel.facets.object.grid.GridFacet;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.specloader.specimpl.ObjectActionMixedIn;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.components.layout.bs3.row.Row;
@@ -54,16 +53,17 @@ extends PanelAbstract<ManagedObject, EntityModel> {
             final ObjectActionMixedIn actionMixedIn = (ObjectActionMixedIn) action;
             final ObjectSpecification mixinSpec = actionMixedIn.getMixinType();
             if(mixinSpec.isViewModel()) {
-                val commonContext = actionModel.getCommonContext();
-                final ManagedObject targetAdapterForMixin = action.realTargetAdapter(actionModel.getActionOwner());
-                final GridFacet gridFacet = mixinSpec.getFacet(GridFacet.class);
-                final Grid gridForMixin = gridFacet.getGrid(targetAdapterForMixin);
-                if(gridForMixin instanceof BS3Grid) {
-                    final BS3Grid bs3Grid = (BS3Grid) gridForMixin;
-                    final EntityModel entityModelForMixin =
+
+                val targetAdapterForMixin = action.realTargetAdapter(actionModel.getActionOwner());
+
+                return Facets.bootstrapGrid(mixinSpec, targetAdapterForMixin)
+                .map(bs3Grid->{
+                    val commonContext = actionModel.getCommonContext();
+                    val entityModelForMixin =
                             EntityModel.ofAdapter(commonContext, targetAdapterForMixin);
-                    return Optional.of(new BS3GridPanel(id, entityModelForMixin, bs3Grid));
-                }
+                    return new BS3GridPanel(id, entityModelForMixin, bs3Grid);
+                });
+
             }
         }
         return Optional.empty();
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/Bs3GridPanelFactory.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/Bs3GridPanelFactory.java
index b897bd9085..9dc336ce84 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/Bs3GridPanelFactory.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/Bs3GridPanelFactory.java
@@ -21,10 +21,7 @@ package org.apache.isis.viewer.wicket.ui.components.layout.bs3;
 import org.apache.wicket.Component;
 import org.apache.wicket.model.IModel;
 
-import org.apache.isis.applib.layout.grid.Grid;
-import org.apache.isis.applib.layout.grid.bootstrap3.BS3Grid;
-import org.apache.isis.core.metamodel.facets.object.grid.GridFacet;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.common.model.components.ComponentType;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
@@ -47,11 +44,11 @@ public class Bs3GridPanelFactory extends EntityComponentFactoryAbstract {
         final EntityModel entityModel = (EntityModel) model;
 
         val objectAdapter = entityModel.getObject();
-        final ObjectSpecification specification = entityModel.getTypeOfSpecification();
-        final GridFacet facet = specification.getFacet(GridFacet.class);
+        val objectSpec = entityModel.getTypeOfSpecification();
 
-        final Grid grid = facet.getGrid(objectAdapter);
-        return ApplicationAdvice.appliesIf(grid instanceof BS3Grid);
+        return ApplicationAdvice.appliesIf(
+                Facets.bootstrapGrid(objectSpec, objectAdapter)
+                .isPresent());
     }
 
     @Override
@@ -59,10 +56,10 @@ public class Bs3GridPanelFactory extends EntityComponentFactoryAbstract {
         final EntityModel entityModel = (EntityModel) model;
 
         val objectAdapter = entityModel.getObject();
-        final ObjectSpecification specification = entityModel.getTypeOfSpecification();
-        final GridFacet facet = specification.getFacet(GridFacet.class);
+        val objectSpec = entityModel.getTypeOfSpecification();
 
-        val grid = (BS3Grid) facet.getGrid(objectAdapter);
-        return new BS3GridPanel(id, entityModel, grid);
+        return Facets.bootstrapGrid(objectSpec, objectAdapter)
+                .map(grid->new BS3GridPanel(id, entityModel, grid))
+                .orElseThrow(); // empty case guarded against by appliesTo(...) above
     }
 }
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
index 161fd23a7a..499f586429 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
@@ -42,10 +42,10 @@ import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.debug._Probe;
 import org.apache.isis.commons.internal.debug._Probe.EntryPoint;
 import org.apache.isis.core.metamodel.commons.ScalarRepresentation;
-import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
 import org.apache.isis.core.metamodel.facets.objectvalue.labelat.LabelAtFacet;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.common.model.components.ComponentType;
 import org.apache.isis.viewer.common.model.feature.ParameterUiModel;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
@@ -411,12 +411,9 @@ implements ScalarModelSubscriber {
 
         Wkt.cssAppend(this, scalarModel.getCssClass());
 
-        scalarModel.lookupFacet(CssClassFacet.class)
-        .ifPresent(cssClassFacet->{
-            val parentAdapter =
-                    scalarModel.getParentUiModel().getManagedObject();
-            Wkt.cssAppend(this, cssClassFacet.cssClass(parentAdapter));
-        });
+        Facets.cssClassFor(scalarModel.getMetaModel(), scalarModel.getParentUiModel().getManagedObject())
+        .ifPresent(cssClass->
+            Wkt.cssAppend(this, cssClass));
     }
 
 
@@ -573,25 +570,8 @@ implements ScalarModelSubscriber {
         Wkt.cssAppend(markupContainer, determineActionLayoutPositioningCss(actionLinks));
     }
 
-    private static String determinePropParamLayoutCss(final ScalarModel model) {
-        final LabelAtFacet facet = model.getFacet(LabelAtFacet.class);
-        if (facet != null) {
-            switch (facet.label()) {
-            case LEFT:
-                return "label-left";
-            case RIGHT:
-                return "label-right";
-            case NONE:
-                return "label-none";
-            case TOP:
-                return "label-top";
-            case DEFAULT:
-            case NOT_SPECIFIED:
-            default:
-                break;
-            }
-        }
-        return "label-left";
+    private static String determinePropParamLayoutCss(final ScalarModel scalarModel) {
+        return Facets.labelAtCss(scalarModel.getMetaModel());
     }
 
     private static String determineActionLayoutPositioningCss(final Can<LinkAndLabel> entityActionLinks) {
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
index 14ace1cf4e..d4a24a1a21 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
@@ -29,10 +29,8 @@ import org.apache.wicket.validation.validator.StringValidator;
 
 import org.apache.isis.commons.internal.assertions._Assert;
 import org.apache.isis.core.metamodel.commons.ScalarRepresentation;
-import org.apache.isis.core.metamodel.facets.objectvalue.maxlen.MaxLengthFacet;
-import org.apache.isis.core.metamodel.facets.objectvalue.multiline.MultiLineFacet;
-import org.apache.isis.core.metamodel.facets.objectvalue.typicallen.TypicalLengthFacet;
 import org.apache.isis.core.metamodel.spec.feature.ObjectFeature;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarFragmentFactory.InputFragment;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
@@ -163,53 +161,33 @@ extends ScalarPanelFormFieldAbstract<T> {
 
     // -- HELPER
 
-    private static Integer getMaxLengthOf(final ScalarModel model) {
-        return model.getScalarTypeSpec()
-                .lookupFacet(MaxLengthFacet.class)
-                .map(MaxLengthFacet::value)
-                .orElse(null);
-    }
-
-    private static Integer getTypicalLenghtOf(final ScalarModel model, final Integer maxLength) {
-        val typicalLength = model.getScalarTypeSpec()
-                .lookupFacet(TypicalLengthFacet.class)
-                .map(TypicalLengthFacet::value)
-                .orElse(null);
-        // doesn't make sense for typical length to be > maxLength
-        if(typicalLength != null
-                && maxLength != null
-                && typicalLength > maxLength) {
-            return maxLength;
-        }
-        return typicalLength;
-    }
-
-    private static Integer getNumberOfLinesOf(final ScalarModel model) {
-        return model.getScalarTypeSpec()
-                .lookupFacet(MultiLineFacet.class)
-                .map(MultiLineFacet::numberOfLines)
-                .orElse(null);
-    }
-
     void setFormComponentAttributes(final FormComponent<?> formComponent) {
         val scalarModel = scalarModel();
+        val scalarTypeSpec = scalarModel.getScalarTypeSpec();
 
         if(formComponent instanceof TextArea) {
-            Wkt.attributeReplace(formComponent, "rows", getNumberOfLinesOf(scalarModel));
+            Facets.multilineNumberOfLines(scalarTypeSpec)
+            .ifPresent(numberOfLines->
+                Wkt.attributeReplace(formComponent, "rows", numberOfLines));
+
             // in conjunction with javascript in jquery.isis.wicket.viewer.js
             // see http://stackoverflow.com/questions/4459610/set-maxlength-in-html-textarea
             //Wkt.attributeReplace(textArea, "maxlength", getMaxLengthOf(scalarModel));
         }
 
-        final Integer maxLength = getMaxLengthOf(scalarModel);
-        if(maxLength != null) {
+        val maxLenIfAny = Facets.maxLength(scalarTypeSpec);
+        maxLenIfAny
+        .ifPresent(maxLength->{
             Wkt.attributeReplace(formComponent, "maxlength", maxLength);
             if(type.equals(String.class)) {
                 formComponent.add(StringValidator.maximumLength(maxLength));
             }
-        }
+        });
+
+        Facets.typicalLength(scalarTypeSpec, maxLenIfAny)
+        .ifPresent(typicalLength->
+            Wkt.attributeReplace(formComponent, "size", typicalLength));
 
-        Wkt.attributeReplace(formComponent, "size", getTypicalLenghtOf(scalarModel, maxLength));
     }
 
 }
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldWithTemporalPicker.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldWithTemporalPicker.java
index 3040d4727e..65ad6f3913 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldWithTemporalPicker.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldWithTemporalPicker.java
@@ -22,7 +22,7 @@ import java.util.Optional;
 
 import org.apache.wicket.markup.html.form.TextField;
 
-import org.apache.isis.core.metamodel.facets.objectvalue.daterenderedadjust.DateRenderAdjustFacet;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarFragmentFactory.InputFragment;
 import org.apache.isis.viewer.wicket.ui.components.scalars.datepicker.TextFieldWithDateTimePicker;
@@ -41,9 +41,7 @@ extends ScalarPanelTextFieldWithValueSemantics<T>  {
     }
 
     protected int getDateRenderAdjustDays() {
-        return scalarModel().lookupFacet(DateRenderAdjustFacet.class)
-            .map(DateRenderAdjustFacet::getDateRenderAdjustDays)
-            .orElse(0);
+        return Facets.dateRenderAdjustDays(scalarModel().getMetaModel());
     }
 
     @Override
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/bool/BooleanPanel.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/bool/BooleanPanel.java
index dfd05e05dd..b190438627 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/bool/BooleanPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/bool/BooleanPanel.java
@@ -130,7 +130,7 @@ extends ScalarPanelFormFieldAbstract<Boolean> {
 
     @Override
     public String getVariation() {
-//        val labelAtFacet = getModel().getFacet(LabelAtFacet.class);
+//        val labelAtFacet = getModel().getFacet(LabelAtFace~t.class);
 //        return labelAtFacet != null
 //                && labelAtFacet.label() == LabelPosition.RIGHT
 //            ? "labelRightPosition"
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
index b5343bebb0..7bce33b875 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
@@ -31,10 +31,9 @@ import org.apache.wicket.util.convert.IConverter;
 import org.wicketstuff.select2.ChoiceProvider;
 import org.wicketstuff.select2.Settings;
 
-import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacet;
 import org.apache.isis.core.metamodel.objectmanager.memento.ObjectMemento;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.common.model.components.ComponentType;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarFragmentFactory.CompactFragment;
@@ -133,10 +132,8 @@ public class ReferencePanel extends ScalarPanelSelectAbstract {
             settings.setPlaceholder(scalarModel.getFriendlyName());
 
         } else if(hasObjectAutoComplete()) {
-            val typeOfSpecification = scalarModel.getScalarTypeSpec();
-            val autoCompleteFacet = typeOfSpecification.getFacet(AutoCompleteFacet.class);
-            final int minLength = autoCompleteFacet.getMinLength();
-            settings.setMinimumInputLength(minLength);
+            Facets.autoCompleteMinLength(scalarModel.getScalarTypeSpec())
+            .ifPresent(settings::setMinimumInputLength);
         }
     }
 
@@ -328,10 +325,7 @@ public class ReferencePanel extends ScalarPanelSelectAbstract {
     }
 
     private boolean hasObjectAutoComplete() {
-        final ObjectSpecification typeOfSpecification = getModel().getScalarTypeSpec();
-        final AutoCompleteFacet autoCompleteFacet =
-                (typeOfSpecification != null)? typeOfSpecification.getFacet(AutoCompleteFacet.class):null;
-                return autoCompleteFacet != null;
+        return Facets.autoCompleteIsPresent(scalarModel().getScalarTypeSpec());
     }
 
 }
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/string/StringPanelFactory.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/string/StringPanelFactory.java
index f4c360c39d..30f0f5d8be 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/string/StringPanelFactory.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/string/StringPanelFactory.java
@@ -20,7 +20,7 @@ package org.apache.isis.viewer.wicket.ui.components.scalars.string;
 
 import org.apache.wicket.Component;
 
-import org.apache.isis.core.metamodel.facets.objectvalue.multiline.MultiLineFacet;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ComponentFactoryScalarAbstract;
 
@@ -34,12 +34,8 @@ public class StringPanelFactory extends ComponentFactoryScalarAbstract {
 
     @Override
     public Component createComponent(final String id, final ScalarModel scalarModel) {
-        final MultiLineFacet multiLineFacet = scalarModel.getFacet(MultiLineFacet.class);
-        if (multiLineFacet != null
-                && !multiLineFacet.getPrecedence().isFallback()) {
-            return new MultiLineStringPanel(id, scalarModel);
-        } else {
-            return new StringPanel(id, scalarModel);
-        }
+        return Facets.multilineIsPresent(scalarModel.getMetaModel())
+            ? new MultiLineStringPanel(id, scalarModel)
+            : new StringPanel(id, scalarModel);
     }
 }
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/value/fallback/ValueFallbackPanelFactory.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/value/fallback/ValueFallbackPanelFactory.java
index ae86a4fd75..5598601e0b 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/value/fallback/ValueFallbackPanelFactory.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/value/fallback/ValueFallbackPanelFactory.java
@@ -21,7 +21,7 @@ package org.apache.isis.viewer.wicket.ui.components.scalars.value.fallback;
 import org.apache.wicket.Component;
 import org.apache.wicket.model.IModel;
 
-import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ComponentFactoryScalarAbstract;
@@ -44,8 +44,7 @@ extends ComponentFactoryScalarAbstract {
             return ApplicationAdvice.DOES_NOT_APPLY;
         }
         final ScalarModel scalarModel = (ScalarModel) model;
-        final ValueFacet<?> valueFacet = scalarModel.getScalarTypeSpec().getFacet(ValueFacet.class);
-        if(valueFacet == null) {
+        if(!Facets.valueIsPresent(scalarModel.getScalarTypeSpec())) {
             return ApplicationAdvice.DOES_NOT_APPLY;
         }
         final boolean hasChoices = scalarModel.hasChoices();
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/providers/ObjectAdapterMementoProviderForReferenceObjectAutoComplete.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/providers/ObjectAdapterMementoProviderForReferenceObjectAutoComplete.java
index f02d772284..992093b210 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/providers/ObjectAdapterMementoProviderForReferenceObjectAutoComplete.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/providers/ObjectAdapterMementoProviderForReferenceObjectAutoComplete.java
@@ -19,9 +19,8 @@
 package org.apache.isis.viewer.wicket.ui.components.widgets.select2.providers;
 
 import org.apache.isis.commons.collections.Can;
-import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
-import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacet;
 import org.apache.isis.core.metamodel.objectmanager.memento.ObjectMemento;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 
 import lombok.val;
@@ -37,12 +36,9 @@ extends ObjectAdapterMementoProviderAbstract {
 
     @Override
     protected Can<ObjectMemento> obtainMementos(final String term) {
-        val typeOfSpecification = getScalarModel().getScalarTypeSpec();
-        val autoCompleteFacet = typeOfSpecification.getFacet(AutoCompleteFacet.class);
-        val autoCompleteAdapters = autoCompleteFacet.execute(term, InteractionInitiatedBy.USER);
-        val commonContext = super.getCommonContext();
-
-        return autoCompleteAdapters.map(commonContext::mementoFor);
+        val scalarTypeSpec = getScalarModel().getScalarTypeSpec();
+        val autoCompleteAdapters = Facets.autoCompleteExecute(scalarTypeSpec, term);
+        return autoCompleteAdapters.map(getCommonContext()::mementoFor);
     }
 
 
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
index 626966a630..712ada3a98 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
@@ -38,12 +38,11 @@ import org.apache.isis.commons.internal.base._Refs.ObjectReference;
 import org.apache.isis.commons.internal.base._Timing;
 import org.apache.isis.commons.internal.debug._Debug;
 import org.apache.isis.commons.internal.debug.xray.XrayUi;
-import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
-import org.apache.isis.core.metamodel.facets.object.grid.GridFacet;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.core.runtime.context.IsisAppCommonContext;
 import org.apache.isis.viewer.common.model.components.ComponentType;
 import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
@@ -177,13 +176,8 @@ public class EntityPage extends PageAbstract {
         }
 
         final ObjectSpecification objectSpec = model.getTypeOfSpecification();
-        final GridFacet gridFacet = objectSpec.getFacet(GridFacet.class);
-        if(gridFacet != null) {
-            // the facet should always exist, in fact
-            // just enough to ask for the metadata.
-            // This will cause the current ObjectSpec to be updated as a side effect.
-            gridFacet.getGrid(objectAdapter);
-        }
+
+        Facets.gridPreload(objectSpec, objectAdapter);
 
         final String titleStr = objectAdapter.titleString();
         setTitle(titleStr);
@@ -191,11 +185,10 @@ public class EntityPage extends PageAbstract {
         WebMarkupContainer entityPageContainer = new WebMarkupContainer("entityPageContainer");
         Wkt.cssAppend(entityPageContainer, objectSpec.getFeatureIdentifier());
 
-        CssClassFacet cssClassFacet = objectSpec.getFacet(CssClassFacet.class);
-        if(cssClassFacet != null) {
-            final String cssClass = cssClassFacet.cssClass(objectAdapter);
-            Wkt.cssAppend(entityPageContainer, cssClass);
-        }
+        Facets.cssClassFor(objectSpec, objectAdapter)
+        .ifPresent(cssClass->
+            Wkt.cssAppend(entityPageContainer, cssClass)
+        );
 
         themeDiv.addOrReplace(entityPageContainer);