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/09/01 03:59:37 UTC

[isis] 02/03: ISIS-3167: implements the remaining VIEWMODEL and ENTITY (not active yet)

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

commit 8a4b5b89ef1273bf93a5f2b262d16dd91fc16347
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Sep 1 05:31:13 2022 +0200

    ISIS-3167: implements the remaining VIEWMODEL and ENTITY (not active
    yet)
---
 .../core/metamodel/object/_ManagedObjectEmpty.java |   3 -
 ...dObjectMixin.java => _ManagedObjectEntity.java} |  59 ++++---
 .../core/metamodel/object/_ManagedObjectMixin.java |   1 -
 .../core/metamodel/object/_ManagedObjectOther.java |  10 +-
 .../metamodel/object/_ManagedObjectService.java    |   1 -
 .../core/metamodel/object/_ManagedObjectValue.java |   1 -
 .../metamodel/object/_ManagedObjectViewmodel.java  | 189 +++++++++++++++++++++
 7 files changed, 233 insertions(+), 31 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectEmpty.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectEmpty.java
index 285211fabf..bf03745c66 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectEmpty.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectEmpty.java
@@ -23,13 +23,10 @@ import java.util.function.Supplier;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
-import lombok.Getter;
-
 /**
  * (package private) specialization corresponding to {@link Specialization#EMPTY}
  * @see ManagedObject.Specialization#EMPTY
  */
-@Getter
 final class _ManagedObjectEmpty
 extends _ManagedObjectSpecified
 implements Bookmarkable.NoBookmark {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectMixin.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectEntity.java
similarity index 56%
copy from core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectMixin.java
copy to core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectEntity.java
index 15fb7fafbd..91b8c9192c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectMixin.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectEntity.java
@@ -18,46 +18,65 @@
  */
 package org.apache.isis.core.metamodel.object;
 
+import java.util.Optional;
 import java.util.function.Supplier;
 
+import org.springframework.lang.Nullable;
+
 import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.commons.internal.assertions._Assert;
-import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
-import lombok.Getter;
 import lombok.NonNull;
-import lombok.experimental.Accessors;
 
 /**
- * (package private) specialization corresponding to {@link Specialization#MIXIN}
- * @see ManagedObject.Specialization#MIXIN
+ * (package private) specialization corresponding to {@link Specialization#ENTITY}
+ * @see ManagedObject.Specialization#ENTITY
  */
-@Getter
-final class _ManagedObjectMixin
-extends _ManagedObjectSpecified
-implements Bookmarkable.NoBookmark {
+final class _ManagedObjectEntity
+extends _ManagedObjectSpecified {
 
-    @Getter(onMethod_ = {@Override}) @Accessors(makeFinal = true)
-    private final @NonNull Object pojo;
+    private /*final*/ @Nullable Object pojo;
+    private final @NonNull Bookmark bookmark;
 
-    _ManagedObjectMixin(
+    _ManagedObjectEntity(
             final ObjectSpecification spec,
-            final Object pojo) {
-        super(ManagedObject.Specialization.MIXIN, spec);
-        _Assert.assertTrue(spec.isMixin());
+            final Object pojo,
+            final @NonNull Bookmark bookmark) {
+        super(ManagedObject.Specialization.ENTITY, spec);
         this.pojo = assertCompliance(pojo);
+        this.bookmark = bookmark;
+    }
+
+    @Override
+    public Optional<Bookmark> getBookmark() {
+        return Optional.of(bookmark);
+    }
+
+    @Override
+    public Optional<Bookmark> getBookmarkRefreshed() {
+        return getBookmark(); // no-op for entities
+    }
+
+    @Override
+    public boolean isBookmarkMemoized() {
+        return true;
     }
 
     @Override
     public void refreshViewmodel(final Supplier<Bookmark> bookmarkSupplier) {
-        // no-op for mixins
+        // no-op for entities
     }
 
     @Override
-    public final String getTitle() {
-        // mixins have no title
-        throw _Exceptions.unexpectedCodeReach();
+    public Object getPojo() {
+        // TODO refetch if required
+        return pojo;
     }
 
+    // -- HELPER
+
+//    private EntityFacet entityFacet() {
+//        return getSpecification().entityFacet().orElseThrow();
+//    }
+
 }
\ No newline at end of file
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectMixin.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectMixin.java
index 15fb7fafbd..e635a0145c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectMixin.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectMixin.java
@@ -33,7 +33,6 @@ import lombok.experimental.Accessors;
  * (package private) specialization corresponding to {@link Specialization#MIXIN}
  * @see ManagedObject.Specialization#MIXIN
  */
-@Getter
 final class _ManagedObjectMixin
 extends _ManagedObjectSpecified
 implements Bookmarkable.NoBookmark {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectOther.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectOther.java
index 62a7a88a98..4618fad95a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectOther.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectOther.java
@@ -31,7 +31,6 @@ import lombok.experimental.Accessors;
  * (package private) specialization corresponding to {@link Specialization#OTHER}
  * @see ManagedObject.Specialization#OTHER
  */
-@Getter
 final class _ManagedObjectOther
 extends _ManagedObjectSpecified
 implements Bookmarkable.NoBookmark {
@@ -53,9 +52,10 @@ implements Bookmarkable.NoBookmark {
         // no-op for other
     }
 
-    @Override
-    public String getTitle() {
-        return "other object";
-    }
+    //TODO to use or not to use?
+//    @Override
+//    public String getTitle() {
+//        return "other object";
+//    }
 
 }
\ No newline at end of file
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectService.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectService.java
index aa9b839b9d..fd1f168a9f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectService.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectService.java
@@ -34,7 +34,6 @@ import lombok.experimental.Accessors;
  * (package private) specialization corresponding to {@link Specialization#SERVICE}
  * @see ManagedObject.Specialization#SERVICE
  */
-@Getter
 final class _ManagedObjectService
 extends _ManagedObjectSpecified {
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectValue.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectValue.java
index 2a6e1be759..f6795095af 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectValue.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectValue.java
@@ -37,7 +37,6 @@ import lombok.experimental.Accessors;
  * (package private) specialization corresponding to {@link Specialization#VALUE}
  * @see ManagedObject.Specialization#VALUE
  */
-@Getter
 final class _ManagedObjectValue
 extends _ManagedObjectSpecified {
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectViewmodel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectViewmodel.java
new file mode 100644
index 0000000000..3ab20f9fd1
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectViewmodel.java
@@ -0,0 +1,189 @@
+/*
+ *  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.object;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.function.Supplier;
+import java.util.function.UnaryOperator;
+
+import org.springframework.lang.Nullable;
+
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.commons.internal.assertions._Assert;
+import org.apache.isis.commons.internal.base._Lazy;
+import org.apache.isis.commons.internal.debug._XrayEvent;
+import org.apache.isis.core.metamodel.context.MetaModelContext;
+import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.val;
+
+/**
+ * (package private) specialization corresponding to {@link Specialization#VIEWMODEL}
+ * @see ManagedObject.Specialization#VIEWMODEL
+ */
+final class _ManagedObjectViewmodel
+extends _ManagedObjectSpecified {
+
+    @Getter(onMethod_ = {@Override})
+    @Nullable private /*final*/ Object pojo;
+
+    protected final _Lazy<Optional<Bookmark>> bookmarkLazy =
+            _Lazy.threadSafe(()->bookmark(this));
+
+    _ManagedObjectViewmodel(
+            final ObjectSpecification spec,
+            final Object pojo,
+            final Optional<Bookmark> bookmarkIfKnown) {
+        super(ManagedObject.Specialization.VIEWMODEL, spec);
+        _Assert.assertTrue(spec.isViewModel());
+        this.pojo = assertCompliance(pojo);
+        if(bookmarkIfKnown.isPresent()) {
+            this.bookmarkLazy.set(bookmarkIfKnown);
+        }
+    }
+
+    @Override
+    public final Optional<Bookmark> getBookmark() {
+        return bookmarkLazy.get();
+    }
+
+    @Override
+    public final boolean isBookmarkMemoized() {
+        return bookmarkLazy.isMemoized();
+    }
+
+    @Override
+    public final Optional<Bookmark> getBookmarkRefreshed() {
+        bookmarkLazy.clear();
+        return getBookmark();
+    }
+
+    private void replaceBookmark(final UnaryOperator<Bookmark> replacer) {
+        final Bookmark old = bookmarkLazy.isMemoized()
+                ? bookmarkLazy.get().orElse(null)
+                : null;
+        bookmarkLazy.clear();
+        bookmarkLazy.set(Optional.ofNullable(replacer.apply(old)));
+    }
+
+    // guards against non-identifiable objects;
+    // historically, we allowed non-identifiable to be handled by the objectManager,
+    // which as a fallback creates 'random' UUIDs
+    private Optional<Bookmark> bookmark(final @Nullable ManagedObject adapter) {
+
+        if(ManagedObjects.isNullOrUnspecifiedOrEmpty(adapter)
+                || adapter.getSpecification().isValue()
+                || !ManagedObjects.isIdentifiable(adapter)) {
+            return Optional.empty();
+        }
+
+        return ManagedObjects.spec(adapter)
+                .map(ObjectSpecification::getMetaModelContext)
+                .map(MetaModelContext::getObjectManager)
+                .map(objectManager->objectManager.bookmarkObject(adapter));
+    }
+
+    // -- REFRESH OPTIMIZATION
+
+    private UUID interactionIdDuringWhichRefreshed = null;
+
+    @Override
+    public final void refreshViewmodel(final @Nullable Supplier<Bookmark> bookmarkSupplier) {
+        val spec = getSpecification();
+        if(spec.isViewModel()) {
+            val viewModelFacet = spec.getFacet(ViewModelFacet.class);
+            if(viewModelFacet.containsEntities()) {
+
+                val shouldRefresh = spec.getMetaModelContext().getInteractionProvider().getInteractionId()
+                .map(this::shouldRefresh)
+                .orElse(true); // if there is no current interaction, refresh regardless; unexpected state, might fail later
+
+                if(!shouldRefresh) {
+                    return;
+                }
+
+                if(isBookmarkMemoized()) {
+                    reloadViewmodelFromMemoizedBookmark();
+                } else {
+                    val bookmark = bookmarkSupplier!=null
+                            ? bookmarkSupplier.get()
+                            : null;
+                    if(bookmark!=null) {
+                        reloadViewmodelFromBookmark(bookmark);
+                    }
+                }
+            }
+        }
+    }
+
+    // -- HELPER
+
+    private boolean shouldRefresh(final @NonNull UUID interactionId) {
+        if(Objects.equals(this.interactionIdDuringWhichRefreshed, interactionId)) {
+            return false; // already refreshed within current interaction
+        }
+        this.interactionIdDuringWhichRefreshed = interactionId;
+        return true;
+    }
+
+    /**
+     * Reload current viewmodel object from memoized bookmark, otherwise does nothing.
+     */
+    private void reloadViewmodelFromMemoizedBookmark() {
+        val spec = getSpecification();
+        if(isBookmarkMemoized()
+                && spec.isViewModel()) {
+
+            val bookmark = getBookmark().get();
+            val viewModelClass = spec.getCorrespondingClass();
+
+            val recreatedViewmodel =
+                    getMetaModelContext().getFactoryService().viewModel(viewModelClass, bookmark);
+
+            _XrayEvent.event("Viewmodel '%s' recreated from memoized bookmark.", viewModelClass.getName());
+
+            replacePojo(old->recreatedViewmodel);
+        }
+    }
+
+    private void reloadViewmodelFromBookmark(final @NonNull Bookmark bookmark) {
+        val spec = getSpecification();
+        if(spec.isViewModel()) {
+            val viewModelClass = spec.getCorrespondingClass();
+
+            val recreatedViewmodel =
+                    getMetaModelContext().getFactoryService().viewModel(viewModelClass, bookmark);
+
+            _XrayEvent.event("Viewmodel '%s' recreated from provided bookmark.", viewModelClass.getName());
+
+            replacePojo(old->recreatedViewmodel);
+            replaceBookmark(old->bookmark);
+        }
+    }
+
+    private void replacePojo(final UnaryOperator<Object> replacer) {
+        pojo = assertCompliance(replacer.apply(pojo));
+    }
+
+}
\ No newline at end of file